]>
Commit | Line | Data |
---|---|---|
18507e1a SF |
1 | /* |
2 | * Copyright (C) 2005-2017 Junjiro R. Okajima | |
3 | * | |
4 | * This program, aufs is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * superblock private data | |
20 | */ | |
21 | ||
22 | #include "aufs.h" | |
23 | ||
24 | /* | |
25 | * they are necessary regardless sysfs is disabled. | |
26 | */ | |
27 | void au_si_free(struct kobject *kobj) | |
28 | { | |
29 | int i; | |
30 | struct au_sbinfo *sbinfo; | |
31 | char *locked __maybe_unused; /* debug only */ | |
32 | ||
33 | sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); | |
34 | for (i = 0; i < AuPlink_NHASH; i++) | |
35 | AuDebugOn(!hlist_empty(&sbinfo->si_plink[i].head)); | |
36 | AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); | |
37 | ||
38 | AuDebugOn(percpu_counter_sum(&sbinfo->si_ninodes)); | |
39 | percpu_counter_destroy(&sbinfo->si_ninodes); | |
40 | AuDebugOn(percpu_counter_sum(&sbinfo->si_nfiles)); | |
41 | percpu_counter_destroy(&sbinfo->si_nfiles); | |
42 | ||
43 | au_rw_write_lock(&sbinfo->si_rwsem); | |
44 | au_br_free(sbinfo); | |
45 | au_rw_write_unlock(&sbinfo->si_rwsem); | |
46 | ||
47 | kfree(sbinfo->si_branch); | |
48 | mutex_destroy(&sbinfo->si_xib_mtx); | |
49 | AuRwDestroy(&sbinfo->si_rwsem); | |
50 | ||
51 | kfree(sbinfo); | |
52 | } | |
53 | ||
54 | int au_si_alloc(struct super_block *sb) | |
55 | { | |
56 | int err, i; | |
57 | struct au_sbinfo *sbinfo; | |
58 | ||
59 | err = -ENOMEM; | |
60 | sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); | |
61 | if (unlikely(!sbinfo)) | |
62 | goto out; | |
63 | ||
64 | /* will be reallocated separately */ | |
65 | sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); | |
66 | if (unlikely(!sbinfo->si_branch)) | |
67 | goto out_sbinfo; | |
68 | ||
69 | err = sysaufs_si_init(sbinfo); | |
70 | if (unlikely(err)) | |
71 | goto out_br; | |
72 | ||
73 | au_nwt_init(&sbinfo->si_nowait); | |
74 | au_rw_init_wlock(&sbinfo->si_rwsem); | |
75 | ||
76 | percpu_counter_init(&sbinfo->si_ninodes, 0, GFP_NOFS); | |
77 | percpu_counter_init(&sbinfo->si_nfiles, 0, GFP_NOFS); | |
78 | ||
79 | sbinfo->si_bbot = -1; | |
80 | sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2; | |
81 | ||
82 | sbinfo->si_wbr_copyup = AuWbrCopyup_Def; | |
83 | sbinfo->si_wbr_create = AuWbrCreate_Def; | |
84 | sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup; | |
85 | sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create; | |
86 | ||
87 | au_fhsm_init(sbinfo); | |
88 | ||
89 | sbinfo->si_mntflags = au_opts_plink(AuOpt_Def); | |
90 | ||
91 | sbinfo->si_xino_jiffy = jiffies; | |
92 | sbinfo->si_xino_expire | |
93 | = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC); | |
94 | mutex_init(&sbinfo->si_xib_mtx); | |
95 | sbinfo->si_xino_brid = -1; | |
96 | /* leave si_xib_last_pindex and si_xib_next_bit */ | |
97 | ||
98 | au_sphl_init(&sbinfo->si_aopen); | |
99 | ||
100 | sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC); | |
101 | sbinfo->si_rdblk = AUFS_RDBLK_DEF; | |
102 | sbinfo->si_rdhash = AUFS_RDHASH_DEF; | |
103 | sbinfo->si_dirwh = AUFS_DIRWH_DEF; | |
104 | ||
105 | for (i = 0; i < AuPlink_NHASH; i++) | |
106 | au_sphl_init(sbinfo->si_plink + i); | |
107 | init_waitqueue_head(&sbinfo->si_plink_wq); | |
108 | spin_lock_init(&sbinfo->si_plink_maint_lock); | |
109 | ||
110 | au_sphl_init(&sbinfo->si_files); | |
111 | ||
112 | /* with getattr by default */ | |
113 | sbinfo->si_iop_array = aufs_iop; | |
114 | ||
115 | /* leave other members for sysaufs and si_mnt. */ | |
116 | sbinfo->si_sb = sb; | |
117 | sb->s_fs_info = sbinfo; | |
118 | si_pid_set(sb); | |
119 | return 0; /* success */ | |
120 | ||
121 | out_br: | |
122 | kfree(sbinfo->si_branch); | |
123 | out_sbinfo: | |
124 | kfree(sbinfo); | |
125 | out: | |
126 | return err; | |
127 | } | |
128 | ||
129 | int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) | |
130 | { | |
131 | int err, sz; | |
132 | struct au_branch **brp; | |
133 | ||
134 | AuRwMustWriteLock(&sbinfo->si_rwsem); | |
135 | ||
136 | err = -ENOMEM; | |
137 | sz = sizeof(*brp) * (sbinfo->si_bbot + 1); | |
138 | if (unlikely(!sz)) | |
139 | sz = sizeof(*brp); | |
140 | brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS, | |
141 | may_shrink); | |
142 | if (brp) { | |
143 | sbinfo->si_branch = brp; | |
144 | err = 0; | |
145 | } | |
146 | ||
147 | return err; | |
148 | } | |
149 | ||
150 | /* ---------------------------------------------------------------------- */ | |
151 | ||
152 | unsigned int au_sigen_inc(struct super_block *sb) | |
153 | { | |
154 | unsigned int gen; | |
155 | struct inode *inode; | |
156 | ||
157 | SiMustWriteLock(sb); | |
158 | ||
159 | gen = ++au_sbi(sb)->si_generation; | |
160 | au_update_digen(sb->s_root); | |
161 | inode = d_inode(sb->s_root); | |
162 | au_update_iigen(inode, /*half*/0); | |
163 | inode->i_version++; | |
164 | return gen; | |
165 | } | |
166 | ||
167 | aufs_bindex_t au_new_br_id(struct super_block *sb) | |
168 | { | |
169 | aufs_bindex_t br_id; | |
170 | int i; | |
171 | struct au_sbinfo *sbinfo; | |
172 | ||
173 | SiMustWriteLock(sb); | |
174 | ||
175 | sbinfo = au_sbi(sb); | |
176 | for (i = 0; i <= AUFS_BRANCH_MAX; i++) { | |
177 | br_id = ++sbinfo->si_last_br_id; | |
178 | AuDebugOn(br_id < 0); | |
179 | if (br_id && au_br_index(sb, br_id) < 0) | |
180 | return br_id; | |
181 | } | |
182 | ||
183 | return -1; | |
184 | } | |
185 | ||
186 | /* ---------------------------------------------------------------------- */ | |
187 | ||
188 | /* it is ok that new 'nwt' tasks are appended while we are sleeping */ | |
189 | int si_read_lock(struct super_block *sb, int flags) | |
190 | { | |
191 | int err; | |
192 | ||
193 | err = 0; | |
194 | if (au_ftest_lock(flags, FLUSH)) | |
195 | au_nwt_flush(&au_sbi(sb)->si_nowait); | |
196 | ||
197 | si_noflush_read_lock(sb); | |
198 | err = au_plink_maint(sb, flags); | |
199 | if (unlikely(err)) | |
200 | si_read_unlock(sb); | |
201 | ||
202 | return err; | |
203 | } | |
204 | ||
205 | int si_write_lock(struct super_block *sb, int flags) | |
206 | { | |
207 | int err; | |
208 | ||
209 | if (au_ftest_lock(flags, FLUSH)) | |
210 | au_nwt_flush(&au_sbi(sb)->si_nowait); | |
211 | ||
212 | si_noflush_write_lock(sb); | |
213 | err = au_plink_maint(sb, flags); | |
214 | if (unlikely(err)) | |
215 | si_write_unlock(sb); | |
216 | ||
217 | return err; | |
218 | } | |
219 | ||
220 | /* dentry and super_block lock. call at entry point */ | |
221 | int aufs_read_lock(struct dentry *dentry, int flags) | |
222 | { | |
223 | int err; | |
224 | struct super_block *sb; | |
225 | ||
226 | sb = dentry->d_sb; | |
227 | err = si_read_lock(sb, flags); | |
228 | if (unlikely(err)) | |
229 | goto out; | |
230 | ||
231 | if (au_ftest_lock(flags, DW)) | |
232 | di_write_lock_child(dentry); | |
233 | else | |
234 | di_read_lock_child(dentry, flags); | |
235 | ||
236 | if (au_ftest_lock(flags, GEN)) { | |
237 | err = au_digen_test(dentry, au_sigen(sb)); | |
238 | if (!au_opt_test(au_mntflags(sb), UDBA_NONE)) | |
239 | AuDebugOn(!err && au_dbrange_test(dentry)); | |
240 | else if (!err) | |
241 | err = au_dbrange_test(dentry); | |
242 | if (unlikely(err)) | |
243 | aufs_read_unlock(dentry, flags); | |
244 | } | |
245 | ||
246 | out: | |
247 | return err; | |
248 | } | |
249 | ||
250 | void aufs_read_unlock(struct dentry *dentry, int flags) | |
251 | { | |
252 | if (au_ftest_lock(flags, DW)) | |
253 | di_write_unlock(dentry); | |
254 | else | |
255 | di_read_unlock(dentry, flags); | |
256 | si_read_unlock(dentry->d_sb); | |
257 | } | |
258 | ||
259 | void aufs_write_lock(struct dentry *dentry) | |
260 | { | |
261 | si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW); | |
262 | di_write_lock_child(dentry); | |
263 | } | |
264 | ||
265 | void aufs_write_unlock(struct dentry *dentry) | |
266 | { | |
267 | di_write_unlock(dentry); | |
268 | si_write_unlock(dentry->d_sb); | |
269 | } | |
270 | ||
271 | int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) | |
272 | { | |
273 | int err; | |
274 | unsigned int sigen; | |
275 | struct super_block *sb; | |
276 | ||
277 | sb = d1->d_sb; | |
278 | err = si_read_lock(sb, flags); | |
279 | if (unlikely(err)) | |
280 | goto out; | |
281 | ||
282 | di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS)); | |
283 | ||
284 | if (au_ftest_lock(flags, GEN)) { | |
285 | sigen = au_sigen(sb); | |
286 | err = au_digen_test(d1, sigen); | |
287 | AuDebugOn(!err && au_dbrange_test(d1)); | |
288 | if (!err) { | |
289 | err = au_digen_test(d2, sigen); | |
290 | AuDebugOn(!err && au_dbrange_test(d2)); | |
291 | } | |
292 | if (unlikely(err)) | |
293 | aufs_read_and_write_unlock2(d1, d2); | |
294 | } | |
295 | ||
296 | out: | |
297 | return err; | |
298 | } | |
299 | ||
300 | void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) | |
301 | { | |
302 | di_write_unlock2(d1, d2); | |
303 | si_read_unlock(d1->d_sb); | |
304 | } |