]>
Commit | Line | Data |
---|---|---|
b6450630 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 | * super_block operations | |
20 | */ | |
21 | ||
22 | #ifndef __AUFS_SUPER_H__ | |
23 | #define __AUFS_SUPER_H__ | |
24 | ||
25 | #ifdef __KERNEL__ | |
26 | ||
27 | #include <linux/fs.h> | |
28 | #include <linux/kobject.h> | |
29 | #include "rwsem.h" | |
30 | #include "spl.h" | |
31 | #include "wkq.h" | |
32 | ||
33 | /* policies to select one among multiple writable branches */ | |
34 | struct au_wbr_copyup_operations { | |
35 | int (*copyup)(struct dentry *dentry); | |
36 | }; | |
37 | ||
38 | #define AuWbr_DIR 1 /* target is a dir */ | |
39 | #define AuWbr_PARENT (1 << 1) /* always require a parent */ | |
40 | ||
41 | #define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name) | |
42 | #define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; } | |
43 | #define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; } | |
44 | ||
45 | struct au_wbr_create_operations { | |
46 | int (*create)(struct dentry *dentry, unsigned int flags); | |
47 | int (*init)(struct super_block *sb); | |
48 | int (*fin)(struct super_block *sb); | |
49 | }; | |
50 | ||
51 | struct au_wbr_mfs { | |
52 | struct mutex mfs_lock; /* protect this structure */ | |
53 | unsigned long mfs_jiffy; | |
54 | unsigned long mfs_expire; | |
55 | aufs_bindex_t mfs_bindex; | |
56 | ||
57 | unsigned long long mfsrr_bytes; | |
58 | unsigned long long mfsrr_watermark; | |
59 | }; | |
60 | ||
61 | #define AuPlink_NHASH 100 | |
62 | static inline int au_plink_hash(ino_t ino) | |
63 | { | |
64 | return ino % AuPlink_NHASH; | |
65 | } | |
66 | ||
67 | /* File-based Hierarchical Storage Management */ | |
68 | struct au_fhsm { | |
69 | #ifdef CONFIG_AUFS_FHSM | |
70 | /* allow only one process who can receive the notification */ | |
71 | spinlock_t fhsm_spin; | |
72 | pid_t fhsm_pid; | |
73 | wait_queue_head_t fhsm_wqh; | |
74 | atomic_t fhsm_readable; | |
75 | ||
76 | /* these are protected by si_rwsem */ | |
77 | unsigned long fhsm_expire; | |
78 | aufs_bindex_t fhsm_bottom; | |
79 | #endif | |
80 | }; | |
81 | ||
82 | struct au_branch; | |
83 | struct au_sbinfo { | |
84 | /* nowait tasks in the system-wide workqueue */ | |
85 | struct au_nowait_tasks si_nowait; | |
86 | ||
87 | /* | |
88 | * tried sb->s_umount, but failed due to the dependecy between i_mutex. | |
89 | * rwsem for au_sbinfo is necessary. | |
90 | */ | |
91 | struct au_rwsem si_rwsem; | |
92 | ||
93 | /* | |
94 | * dirty approach to protect sb->sb_inodes and ->s_files (gone) from | |
95 | * remount. | |
96 | */ | |
97 | struct percpu_counter si_ninodes, si_nfiles; | |
98 | ||
99 | /* branch management */ | |
100 | unsigned int si_generation; | |
101 | ||
102 | /* see AuSi_ flags */ | |
103 | unsigned char au_si_status; | |
104 | ||
105 | aufs_bindex_t si_bbot; | |
106 | ||
107 | /* dirty trick to keep br_id plus */ | |
108 | unsigned int si_last_br_id : | |
109 | sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; | |
110 | struct au_branch **si_branch; | |
111 | ||
112 | /* policy to select a writable branch */ | |
113 | unsigned char si_wbr_copyup; | |
114 | unsigned char si_wbr_create; | |
115 | struct au_wbr_copyup_operations *si_wbr_copyup_ops; | |
116 | struct au_wbr_create_operations *si_wbr_create_ops; | |
117 | ||
118 | /* round robin */ | |
119 | atomic_t si_wbr_rr_next; | |
120 | ||
121 | /* most free space */ | |
122 | struct au_wbr_mfs si_wbr_mfs; | |
123 | ||
124 | /* File-based Hierarchical Storage Management */ | |
125 | struct au_fhsm si_fhsm; | |
126 | ||
127 | /* mount flags */ | |
128 | /* include/asm-ia64/siginfo.h defines a macro named si_flags */ | |
129 | unsigned int si_mntflags; | |
130 | ||
131 | /* external inode number (bitmap and translation table) */ | |
132 | vfs_readf_t si_xread; | |
133 | vfs_writef_t si_xwrite; | |
134 | struct file *si_xib; | |
135 | struct mutex si_xib_mtx; /* protect xib members */ | |
136 | unsigned long *si_xib_buf; | |
137 | unsigned long si_xib_last_pindex; | |
138 | int si_xib_next_bit; | |
139 | aufs_bindex_t si_xino_brid; | |
140 | unsigned long si_xino_jiffy; | |
141 | unsigned long si_xino_expire; | |
142 | /* reserved for future use */ | |
143 | /* unsigned long long si_xib_limit; */ /* Max xib file size */ | |
144 | ||
145 | #ifdef CONFIG_AUFS_EXPORT | |
146 | /* i_generation */ | |
147 | struct file *si_xigen; | |
148 | atomic_t si_xigen_next; | |
149 | #endif | |
150 | ||
151 | /* dirty trick to suppoer atomic_open */ | |
152 | struct au_sphlhead si_aopen; | |
153 | ||
154 | /* vdir parameters */ | |
155 | unsigned long si_rdcache; /* max cache time in jiffies */ | |
156 | unsigned int si_rdblk; /* deblk size */ | |
157 | unsigned int si_rdhash; /* hash size */ | |
158 | ||
159 | /* | |
160 | * If the number of whiteouts are larger than si_dirwh, leave all of | |
161 | * them after au_whtmp_ren to reduce the cost of rmdir(2). | |
162 | * future fsck.aufs or kernel thread will remove them later. | |
163 | * Otherwise, remove all whiteouts and the dir in rmdir(2). | |
164 | */ | |
165 | unsigned int si_dirwh; | |
166 | ||
167 | /* pseudo_link list */ | |
168 | struct au_sphlhead si_plink[AuPlink_NHASH]; | |
169 | wait_queue_head_t si_plink_wq; | |
170 | spinlock_t si_plink_maint_lock; | |
171 | pid_t si_plink_maint_pid; | |
172 | ||
173 | /* file list */ | |
174 | struct au_sphlhead si_files; | |
175 | ||
176 | /* with/without getattr, brother of sb->s_d_op */ | |
177 | struct inode_operations *si_iop_array; | |
178 | ||
179 | /* | |
180 | * sysfs and lifetime management. | |
181 | * this is not a small structure and it may be a waste of memory in case | |
182 | * of sysfs is disabled, particulary when many aufs-es are mounted. | |
183 | * but using sysfs is majority. | |
184 | */ | |
185 | struct kobject si_kobj; | |
186 | #ifdef CONFIG_DEBUG_FS | |
187 | struct dentry *si_dbgaufs; | |
188 | struct dentry *si_dbgaufs_plink; | |
189 | struct dentry *si_dbgaufs_xib; | |
190 | #ifdef CONFIG_AUFS_EXPORT | |
191 | struct dentry *si_dbgaufs_xigen; | |
192 | #endif | |
193 | #endif | |
194 | ||
195 | #ifdef CONFIG_AUFS_SBILIST | |
196 | struct hlist_node si_list; | |
197 | #endif | |
198 | ||
199 | /* dirty, necessary for unmounting, sysfs and sysrq */ | |
200 | struct super_block *si_sb; | |
201 | }; | |
202 | ||
203 | /* sbinfo status flags */ | |
204 | /* | |
205 | * set true when refresh_dirs() failed at remount time. | |
206 | * then try refreshing dirs at access time again. | |
207 | * if it is false, refreshing dirs at access time is unnecesary | |
208 | */ | |
209 | #define AuSi_FAILED_REFRESH_DIR 1 | |
210 | #define AuSi_FHSM (1 << 1) /* fhsm is active now */ | |
211 | #define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */ | |
212 | ||
213 | #ifndef CONFIG_AUFS_FHSM | |
214 | #undef AuSi_FHSM | |
215 | #define AuSi_FHSM 0 | |
216 | #endif | |
217 | ||
218 | static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, | |
219 | unsigned int flag) | |
220 | { | |
221 | AuRwMustAnyLock(&sbi->si_rwsem); | |
222 | return sbi->au_si_status & flag; | |
223 | } | |
224 | #define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) | |
225 | #define au_fset_si(sbinfo, name) do { \ | |
226 | AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ | |
227 | (sbinfo)->au_si_status |= AuSi_##name; \ | |
228 | } while (0) | |
229 | #define au_fclr_si(sbinfo, name) do { \ | |
230 | AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ | |
231 | (sbinfo)->au_si_status &= ~AuSi_##name; \ | |
232 | } while (0) | |
233 | ||
234 | /* ---------------------------------------------------------------------- */ | |
235 | ||
236 | /* policy to select one among writable branches */ | |
237 | #define AuWbrCopyup(sbinfo, ...) \ | |
238 | ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) | |
239 | #define AuWbrCreate(sbinfo, ...) \ | |
240 | ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) | |
241 | ||
242 | /* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ | |
243 | #define AuLock_DW 1 /* write-lock dentry */ | |
244 | #define AuLock_IR (1 << 1) /* read-lock inode */ | |
245 | #define AuLock_IW (1 << 2) /* write-lock inode */ | |
246 | #define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ | |
247 | #define AuLock_DIRS (1 << 4) /* target is a pair of dirs */ | |
248 | /* except RENAME_EXCHANGE */ | |
249 | #define AuLock_NOPLM (1 << 5) /* return err in plm mode */ | |
250 | #define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ | |
251 | #define AuLock_GEN (1 << 7) /* test digen/iigen */ | |
252 | #define au_ftest_lock(flags, name) ((flags) & AuLock_##name) | |
253 | #define au_fset_lock(flags, name) \ | |
254 | do { (flags) |= AuLock_##name; } while (0) | |
255 | #define au_fclr_lock(flags, name) \ | |
256 | do { (flags) &= ~AuLock_##name; } while (0) | |
257 | ||
258 | /* ---------------------------------------------------------------------- */ | |
259 | ||
260 | /* super.c */ | |
261 | extern struct file_system_type aufs_fs_type; | |
262 | struct inode *au_iget_locked(struct super_block *sb, ino_t ino); | |
263 | typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array, | |
264 | unsigned long long max, void *arg); | |
265 | void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, | |
266 | struct super_block *sb, void *arg); | |
267 | struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); | |
268 | void au_iarray_free(struct inode **a, unsigned long long max); | |
269 | ||
270 | /* sbinfo.c */ | |
271 | void au_si_free(struct kobject *kobj); | |
272 | int au_si_alloc(struct super_block *sb); | |
273 | int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); | |
274 | ||
275 | unsigned int au_sigen_inc(struct super_block *sb); | |
276 | aufs_bindex_t au_new_br_id(struct super_block *sb); | |
277 | ||
278 | int si_read_lock(struct super_block *sb, int flags); | |
279 | int si_write_lock(struct super_block *sb, int flags); | |
280 | int aufs_read_lock(struct dentry *dentry, int flags); | |
281 | void aufs_read_unlock(struct dentry *dentry, int flags); | |
282 | void aufs_write_lock(struct dentry *dentry); | |
283 | void aufs_write_unlock(struct dentry *dentry); | |
284 | int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); | |
285 | void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); | |
286 | ||
287 | /* wbr_policy.c */ | |
288 | extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; | |
289 | extern struct au_wbr_create_operations au_wbr_create_ops[]; | |
290 | int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); | |
291 | int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex); | |
292 | int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop); | |
293 | ||
294 | /* mvdown.c */ | |
295 | int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg); | |
296 | ||
297 | #ifdef CONFIG_AUFS_FHSM | |
298 | /* fhsm.c */ | |
299 | ||
300 | static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm) | |
301 | { | |
302 | pid_t pid; | |
303 | ||
304 | spin_lock(&fhsm->fhsm_spin); | |
305 | pid = fhsm->fhsm_pid; | |
306 | spin_unlock(&fhsm->fhsm_spin); | |
307 | ||
308 | return pid; | |
309 | } | |
310 | ||
311 | void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force); | |
312 | void au_fhsm_wrote_all(struct super_block *sb, int force); | |
313 | int au_fhsm_fd(struct super_block *sb, int oflags); | |
314 | int au_fhsm_br_alloc(struct au_branch *br); | |
315 | void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex); | |
316 | void au_fhsm_fin(struct super_block *sb); | |
317 | void au_fhsm_init(struct au_sbinfo *sbinfo); | |
318 | void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec); | |
319 | void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo); | |
320 | #else | |
321 | AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex, | |
322 | int force) | |
323 | AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force) | |
324 | AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags) | |
325 | AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm) | |
326 | AuStubInt0(au_fhsm_br_alloc, struct au_branch *br) | |
327 | AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex) | |
328 | AuStubVoid(au_fhsm_fin, struct super_block *sb) | |
329 | AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo) | |
330 | AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec) | |
331 | AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo) | |
332 | #endif | |
333 | ||
334 | /* ---------------------------------------------------------------------- */ | |
335 | ||
336 | static inline struct au_sbinfo *au_sbi(struct super_block *sb) | |
337 | { | |
338 | return sb->s_fs_info; | |
339 | } | |
340 | ||
341 | /* ---------------------------------------------------------------------- */ | |
342 | ||
343 | #ifdef CONFIG_AUFS_EXPORT | |
344 | int au_test_nfsd(void); | |
345 | void au_export_init(struct super_block *sb); | |
346 | void au_xigen_inc(struct inode *inode); | |
347 | int au_xigen_new(struct inode *inode); | |
348 | int au_xigen_set(struct super_block *sb, struct file *base); | |
349 | void au_xigen_clr(struct super_block *sb); | |
350 | ||
351 | static inline int au_busy_or_stale(void) | |
352 | { | |
353 | if (!au_test_nfsd()) | |
354 | return -EBUSY; | |
355 | return -ESTALE; | |
356 | } | |
357 | #else | |
358 | AuStubInt0(au_test_nfsd, void) | |
359 | AuStubVoid(au_export_init, struct super_block *sb) | |
360 | AuStubVoid(au_xigen_inc, struct inode *inode) | |
361 | AuStubInt0(au_xigen_new, struct inode *inode) | |
362 | AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base) | |
363 | AuStubVoid(au_xigen_clr, struct super_block *sb) | |
364 | AuStub(int, au_busy_or_stale, return -EBUSY, void) | |
365 | #endif /* CONFIG_AUFS_EXPORT */ | |
366 | ||
367 | /* ---------------------------------------------------------------------- */ | |
368 | ||
369 | #ifdef CONFIG_AUFS_SBILIST | |
370 | /* module.c */ | |
371 | extern struct au_sphlhead au_sbilist; | |
372 | ||
373 | static inline void au_sbilist_init(void) | |
374 | { | |
375 | au_sphl_init(&au_sbilist); | |
376 | } | |
377 | ||
378 | static inline void au_sbilist_add(struct super_block *sb) | |
379 | { | |
380 | au_sphl_add(&au_sbi(sb)->si_list, &au_sbilist); | |
381 | } | |
382 | ||
383 | static inline void au_sbilist_del(struct super_block *sb) | |
384 | { | |
385 | au_sphl_del(&au_sbi(sb)->si_list, &au_sbilist); | |
386 | } | |
387 | ||
388 | #ifdef CONFIG_AUFS_MAGIC_SYSRQ | |
389 | static inline void au_sbilist_lock(void) | |
390 | { | |
391 | spin_lock(&au_sbilist.spin); | |
392 | } | |
393 | ||
394 | static inline void au_sbilist_unlock(void) | |
395 | { | |
396 | spin_unlock(&au_sbilist.spin); | |
397 | } | |
398 | #define AuGFP_SBILIST GFP_ATOMIC | |
399 | #else | |
400 | AuStubVoid(au_sbilist_lock, void) | |
401 | AuStubVoid(au_sbilist_unlock, void) | |
402 | #define AuGFP_SBILIST GFP_NOFS | |
403 | #endif /* CONFIG_AUFS_MAGIC_SYSRQ */ | |
404 | #else | |
405 | AuStubVoid(au_sbilist_init, void) | |
406 | AuStubVoid(au_sbilist_add, struct super_block *sb) | |
407 | AuStubVoid(au_sbilist_del, struct super_block *sb) | |
408 | AuStubVoid(au_sbilist_lock, void) | |
409 | AuStubVoid(au_sbilist_unlock, void) | |
410 | #define AuGFP_SBILIST GFP_NOFS | |
411 | #endif | |
412 | ||
413 | /* ---------------------------------------------------------------------- */ | |
414 | ||
415 | static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) | |
416 | { | |
417 | /* | |
418 | * This function is a dynamic '__init' function actually, | |
419 | * so the tiny check for si_rwsem is unnecessary. | |
420 | */ | |
421 | /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ | |
422 | #ifdef CONFIG_DEBUG_FS | |
423 | sbinfo->si_dbgaufs = NULL; | |
424 | sbinfo->si_dbgaufs_plink = NULL; | |
425 | sbinfo->si_dbgaufs_xib = NULL; | |
426 | #ifdef CONFIG_AUFS_EXPORT | |
427 | sbinfo->si_dbgaufs_xigen = NULL; | |
428 | #endif | |
429 | #endif | |
430 | } | |
431 | ||
432 | /* ---------------------------------------------------------------------- */ | |
433 | ||
434 | /* current->atomic_flags */ | |
435 | /* this value should never corrupt the ones defined in linux/sched.h */ | |
436 | #define PFA_AUFS 7 | |
437 | ||
438 | TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */ | |
439 | TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */ | |
440 | TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */ | |
441 | ||
442 | static inline int si_pid_test(struct super_block *sb) | |
443 | { | |
444 | return !!task_test_aufs(current); | |
445 | } | |
446 | ||
447 | static inline void si_pid_clr(struct super_block *sb) | |
448 | { | |
449 | AuDebugOn(!task_test_aufs(current)); | |
450 | task_clear_aufs(current); | |
451 | } | |
452 | ||
453 | static inline void si_pid_set(struct super_block *sb) | |
454 | { | |
455 | AuDebugOn(task_test_aufs(current)); | |
456 | task_set_aufs(current); | |
457 | } | |
458 | ||
459 | /* ---------------------------------------------------------------------- */ | |
460 | ||
461 | /* lock superblock. mainly for entry point functions */ | |
462 | /* | |
463 | * __si_read_lock, __si_write_lock, | |
464 | * __si_read_unlock, __si_write_unlock, __si_downgrade_lock | |
465 | */ | |
466 | AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem); | |
467 | ||
468 | #define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) | |
469 | #define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) | |
470 | #define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) | |
471 | ||
472 | static inline void si_noflush_read_lock(struct super_block *sb) | |
473 | { | |
474 | __si_read_lock(sb); | |
475 | si_pid_set(sb); | |
476 | } | |
477 | ||
478 | static inline int si_noflush_read_trylock(struct super_block *sb) | |
479 | { | |
480 | int locked; | |
481 | ||
482 | locked = __si_read_trylock(sb); | |
483 | if (locked) | |
484 | si_pid_set(sb); | |
485 | return locked; | |
486 | } | |
487 | ||
488 | static inline void si_noflush_write_lock(struct super_block *sb) | |
489 | { | |
490 | __si_write_lock(sb); | |
491 | si_pid_set(sb); | |
492 | } | |
493 | ||
494 | static inline int si_noflush_write_trylock(struct super_block *sb) | |
495 | { | |
496 | int locked; | |
497 | ||
498 | locked = __si_write_trylock(sb); | |
499 | if (locked) | |
500 | si_pid_set(sb); | |
501 | return locked; | |
502 | } | |
503 | ||
504 | #if 0 /* reserved */ | |
505 | static inline int si_read_trylock(struct super_block *sb, int flags) | |
506 | { | |
507 | if (au_ftest_lock(flags, FLUSH)) | |
508 | au_nwt_flush(&au_sbi(sb)->si_nowait); | |
509 | return si_noflush_read_trylock(sb); | |
510 | } | |
511 | #endif | |
512 | ||
513 | static inline void si_read_unlock(struct super_block *sb) | |
514 | { | |
515 | si_pid_clr(sb); | |
516 | __si_read_unlock(sb); | |
517 | } | |
518 | ||
519 | #if 0 /* reserved */ | |
520 | static inline int si_write_trylock(struct super_block *sb, int flags) | |
521 | { | |
522 | if (au_ftest_lock(flags, FLUSH)) | |
523 | au_nwt_flush(&au_sbi(sb)->si_nowait); | |
524 | return si_noflush_write_trylock(sb); | |
525 | } | |
526 | #endif | |
527 | ||
528 | static inline void si_write_unlock(struct super_block *sb) | |
529 | { | |
530 | si_pid_clr(sb); | |
531 | __si_write_unlock(sb); | |
532 | } | |
533 | ||
534 | #if 0 /* reserved */ | |
535 | static inline void si_downgrade_lock(struct super_block *sb) | |
536 | { | |
537 | __si_downgrade_lock(sb); | |
538 | } | |
539 | #endif | |
540 | ||
541 | /* ---------------------------------------------------------------------- */ | |
542 | ||
543 | static inline aufs_bindex_t au_sbbot(struct super_block *sb) | |
544 | { | |
545 | SiMustAnyLock(sb); | |
546 | return au_sbi(sb)->si_bbot; | |
547 | } | |
548 | ||
549 | static inline unsigned int au_mntflags(struct super_block *sb) | |
550 | { | |
551 | SiMustAnyLock(sb); | |
552 | return au_sbi(sb)->si_mntflags; | |
553 | } | |
554 | ||
555 | static inline unsigned int au_sigen(struct super_block *sb) | |
556 | { | |
557 | SiMustAnyLock(sb); | |
558 | return au_sbi(sb)->si_generation; | |
559 | } | |
560 | ||
561 | static inline unsigned long long au_ninodes(struct super_block *sb) | |
562 | { | |
563 | s64 n = percpu_counter_sum(&au_sbi(sb)->si_ninodes); | |
564 | ||
565 | BUG_ON(n < 0); | |
566 | return n; | |
567 | } | |
568 | ||
569 | static inline void au_ninodes_inc(struct super_block *sb) | |
570 | { | |
571 | percpu_counter_inc(&au_sbi(sb)->si_ninodes); | |
572 | } | |
573 | ||
574 | static inline void au_ninodes_dec(struct super_block *sb) | |
575 | { | |
576 | percpu_counter_dec(&au_sbi(sb)->si_ninodes); | |
577 | } | |
578 | ||
579 | static inline unsigned long long au_nfiles(struct super_block *sb) | |
580 | { | |
581 | s64 n = percpu_counter_sum(&au_sbi(sb)->si_nfiles); | |
582 | ||
583 | BUG_ON(n < 0); | |
584 | return n; | |
585 | } | |
586 | ||
587 | static inline void au_nfiles_inc(struct super_block *sb) | |
588 | { | |
589 | percpu_counter_inc(&au_sbi(sb)->si_nfiles); | |
590 | } | |
591 | ||
592 | static inline void au_nfiles_dec(struct super_block *sb) | |
593 | { | |
594 | percpu_counter_dec(&au_sbi(sb)->si_nfiles); | |
595 | } | |
596 | ||
597 | static inline struct au_branch *au_sbr(struct super_block *sb, | |
598 | aufs_bindex_t bindex) | |
599 | { | |
600 | SiMustAnyLock(sb); | |
601 | return au_sbi(sb)->si_branch[0 + bindex]; | |
602 | } | |
603 | ||
604 | static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid) | |
605 | { | |
606 | SiMustWriteLock(sb); | |
607 | au_sbi(sb)->si_xino_brid = brid; | |
608 | } | |
609 | ||
610 | static inline aufs_bindex_t au_xino_brid(struct super_block *sb) | |
611 | { | |
612 | SiMustAnyLock(sb); | |
613 | return au_sbi(sb)->si_xino_brid; | |
614 | } | |
615 | ||
616 | #endif /* __KERNEL__ */ | |
617 | #endif /* __AUFS_SUPER_H__ */ |