sbinfo.c 3.24 KB
Newer Older
J. R. Okajima's avatar
J. R. Okajima committed
1
2
3
4
5
6
7
8
9
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2005-2019 Junjiro R. Okajima
 */

/*
 * superblock private data
 */

J. R. Okajima's avatar
J. R. Okajima committed
10
#include <linux/iversion.h>
J. R. Okajima's avatar
J. R. Okajima committed
11
12
13
14
15
16
17
18
19
20
#include "aufs.h"

/*
 * they are necessary regardless sysfs is disabled.
 */
void au_si_free(struct kobject *kobj)
{
	struct au_sbinfo *sbinfo;

	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
J. R. Okajima's avatar
J. R. Okajima committed
21
	AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
22
23
24
25
26

	au_rw_write_lock(&sbinfo->si_rwsem);
	au_br_free(sbinfo);
	au_rw_write_unlock(&sbinfo->si_rwsem);

J. R. Okajima's avatar
J. R. Okajima committed
27
	au_kfree_try_rcu(sbinfo->si_branch);
J. R. Okajima's avatar
J. R. Okajima committed
28
	mutex_destroy(&sbinfo->si_xib_mtx);
J. R. Okajima's avatar
J. R. Okajima committed
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
	AuRwDestroy(&sbinfo->si_rwsem);

	au_kfree_rcu(sbinfo);
}

int au_si_alloc(struct super_block *sb)
{
	int err;
	struct au_sbinfo *sbinfo;

	err = -ENOMEM;
	sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
	if (unlikely(!sbinfo))
		goto out;

	/* will be reallocated separately */
	sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
	if (unlikely(!sbinfo->si_branch))
		goto out_sbinfo;

J. R. Okajima's avatar
J. R. Okajima committed
49
50
51
52
	err = sysaufs_si_init(sbinfo);
	if (unlikely(err))
		goto out_br;

J. R. Okajima's avatar
J. R. Okajima committed
53
	au_nwt_init(&sbinfo->si_nowait);
J. R. Okajima's avatar
J. R. Okajima committed
54
55
56
	au_rw_init_wlock(&sbinfo->si_rwsem);

	sbinfo->si_bbot = -1;
57
	sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
J. R. Okajima's avatar
J. R. Okajima committed
58

J. R. Okajima's avatar
J. R. Okajima committed
59
60
	sbinfo->si_mntflags = AuOpt_Def;

J. R. Okajima's avatar
J. R. Okajima committed
61
62
63
	sbinfo->si_xino_jiffy = jiffies;
	sbinfo->si_xino_expire
		= msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
J. R. Okajima's avatar
J. R. Okajima committed
64
65
66
	mutex_init(&sbinfo->si_xib_mtx);
	/* leave si_xib_last_pindex and si_xib_next_bit */

J. R. Okajima's avatar
J. R. Okajima committed
67
	/* leave other members for sysaufs and si_mnt. */
J. R. Okajima's avatar
J. R. Okajima committed
68
	sbinfo->si_sb = sb;
J. R. Okajima's avatar
J. R. Okajima committed
69
70
71
	sb->s_fs_info = sbinfo;
	return 0; /* success */

J. R. Okajima's avatar
J. R. Okajima committed
72
out_br:
J. R. Okajima's avatar
J. R. Okajima committed
73
74
75
76
77
78
	au_kfree_try_rcu(sbinfo->si_branch);
out_sbinfo:
	au_kfree_rcu(sbinfo);
out:
	return err;
}
J. R. Okajima's avatar
J. R. Okajima committed
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
{
	int err, sz;
	struct au_branch **brp;

	AuRwMustWriteLock(&sbinfo->si_rwsem);

	err = -ENOMEM;
	sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
	if (unlikely(!sz))
		sz = sizeof(*brp);
	brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
			   may_shrink);
	if (brp) {
		sbinfo->si_branch = brp;
		err = 0;
	}

	return err;
}

J. R. Okajima's avatar
J. R. Okajima committed
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* ---------------------------------------------------------------------- */

unsigned int au_sigen_inc(struct super_block *sb)
{
	unsigned int gen;
	struct inode *inode;

	SiMustWriteLock(sb);

	gen = ++au_sbi(sb)->si_generation;
	au_update_digen(sb->s_root);
	inode = d_inode(sb->s_root);
	au_update_iigen(inode, /*half*/0);
	inode_inc_iversion(inode);
	return gen;
}
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

aufs_bindex_t au_new_br_id(struct super_block *sb)
{
	aufs_bindex_t br_id;
	int i;
	struct au_sbinfo *sbinfo;

	SiMustWriteLock(sb);

	sbinfo = au_sbi(sb);
	for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
		br_id = ++sbinfo->si_last_br_id;
		AuDebugOn(br_id < 0);
		if (br_id && au_br_index(sb, br_id) < 0)
			return br_id;
	}

	return -1;
}
J. R. Okajima's avatar
J. R. Okajima committed
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

/* ---------------------------------------------------------------------- */

/* it is ok that new 'nwt' tasks are appended while we are sleeping */
int si_read_lock(struct super_block *sb, int flags)
{
	if (au_ftest_lock(flags, FLUSH))
		au_nwt_flush(&au_sbi(sb)->si_nowait);

	si_noflush_read_lock(sb);

	return 0; /* re-commit later */
}

int si_write_lock(struct super_block *sb, int flags)
{
	if (au_ftest_lock(flags, FLUSH))
		au_nwt_flush(&au_sbi(sb)->si_nowait);

	si_noflush_write_lock(sb);

	return 0; /* re-commit later */
}