]>
Commit | Line | Data |
---|---|---|
e14748e8 SF |
1 | /* |
2 | * Copyright (C) 2005-2016 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 | * inode operations | |
20 | */ | |
21 | ||
22 | #ifndef __AUFS_INODE_H__ | |
23 | #define __AUFS_INODE_H__ | |
24 | ||
25 | #ifdef __KERNEL__ | |
26 | ||
27 | #include <linux/fsnotify.h> | |
28 | #include "rwsem.h" | |
29 | ||
30 | struct vfsmount; | |
31 | ||
32 | struct au_hnotify { | |
33 | #ifdef CONFIG_AUFS_HNOTIFY | |
34 | #ifdef CONFIG_AUFS_HFSNOTIFY | |
35 | /* never use fsnotify_add_vfsmount_mark() */ | |
36 | struct fsnotify_mark hn_mark; | |
37 | #endif | |
38 | union { | |
39 | struct inode *hn_aufs_inode; /* no get/put */ | |
40 | struct llist_node hn_lnode; /* delayed free */ | |
41 | }; | |
42 | #endif | |
43 | } ____cacheline_aligned_in_smp; | |
44 | ||
45 | struct au_hinode { | |
46 | struct inode *hi_inode; | |
47 | aufs_bindex_t hi_id; | |
48 | #ifdef CONFIG_AUFS_HNOTIFY | |
49 | struct au_hnotify *hi_notify; | |
50 | #endif | |
51 | ||
52 | /* reference to the copied-up whiteout with get/put */ | |
53 | struct dentry *hi_whdentry; | |
54 | }; | |
55 | ||
56 | /* ig_flags */ | |
57 | #define AuIG_HALF_REFRESHED 1 | |
58 | #define au_ig_ftest(flags, name) ((flags) & AuIG_##name) | |
59 | #define au_ig_fset(flags, name) \ | |
60 | do { (flags) |= AuIG_##name; } while (0) | |
61 | #define au_ig_fclr(flags, name) \ | |
62 | do { (flags) &= ~AuIG_##name; } while (0) | |
63 | ||
64 | struct au_iigen { | |
65 | spinlock_t ig_spin; | |
66 | __u32 ig_generation, ig_flags; | |
67 | }; | |
68 | ||
69 | struct au_vdir; | |
70 | struct au_iinfo { | |
71 | struct au_iigen ii_generation; | |
72 | struct super_block *ii_hsb1; /* no get/put */ | |
73 | ||
74 | struct au_rwsem ii_rwsem; | |
75 | aufs_bindex_t ii_btop, ii_bbot; | |
76 | __u32 ii_higen; | |
77 | struct au_hinode *ii_hinode; | |
78 | struct au_vdir *ii_vdir; | |
79 | }; | |
80 | ||
81 | struct au_icntnr { | |
82 | struct au_iinfo iinfo; | |
83 | struct inode vfs_inode; | |
84 | union { | |
85 | struct hlist_node plink; | |
86 | struct llist_node lnode; /* delayed free */ | |
87 | }; | |
88 | } ____cacheline_aligned_in_smp; | |
89 | ||
90 | /* au_pin flags */ | |
91 | #define AuPin_DI_LOCKED 1 | |
92 | #define AuPin_MNT_WRITE (1 << 1) | |
93 | #define au_ftest_pin(flags, name) ((flags) & AuPin_##name) | |
94 | #define au_fset_pin(flags, name) \ | |
95 | do { (flags) |= AuPin_##name; } while (0) | |
96 | #define au_fclr_pin(flags, name) \ | |
97 | do { (flags) &= ~AuPin_##name; } while (0) | |
98 | ||
99 | struct au_pin { | |
100 | /* input */ | |
101 | struct dentry *dentry; | |
102 | unsigned int udba; | |
103 | unsigned char lsc_di, lsc_hi, flags; | |
104 | aufs_bindex_t bindex; | |
105 | ||
106 | /* output */ | |
107 | struct dentry *parent; | |
108 | struct au_hinode *hdir; | |
109 | struct vfsmount *h_mnt; | |
110 | ||
111 | /* temporary unlock/relock for copyup */ | |
112 | struct dentry *h_dentry, *h_parent; | |
113 | struct au_branch *br; | |
114 | struct task_struct *task; | |
115 | }; | |
116 | ||
117 | void au_pin_hdir_unlock(struct au_pin *p); | |
118 | int au_pin_hdir_lock(struct au_pin *p); | |
119 | int au_pin_hdir_relock(struct au_pin *p); | |
120 | void au_pin_hdir_acquire_nest(struct au_pin *p); | |
121 | void au_pin_hdir_release(struct au_pin *p); | |
122 | ||
123 | /* ---------------------------------------------------------------------- */ | |
124 | ||
125 | static inline struct au_iinfo *au_ii(struct inode *inode) | |
126 | { | |
127 | BUG_ON(is_bad_inode(inode)); | |
128 | return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); | |
129 | } | |
130 | ||
131 | /* ---------------------------------------------------------------------- */ | |
132 | ||
133 | /* inode.c */ | |
134 | struct inode *au_igrab(struct inode *inode); | |
135 | void au_refresh_iop(struct inode *inode, int force_getattr); | |
136 | int au_refresh_hinode_self(struct inode *inode); | |
137 | int au_refresh_hinode(struct inode *inode, struct dentry *dentry); | |
138 | int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, | |
139 | unsigned int d_type, ino_t *ino); | |
140 | struct inode *au_new_inode(struct dentry *dentry, int must_new); | |
141 | int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, | |
142 | struct inode *inode); | |
143 | int au_test_h_perm(struct inode *h_inode, int mask); | |
144 | int au_test_h_perm_sio(struct inode *h_inode, int mask); | |
145 | ||
146 | static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, | |
147 | ino_t h_ino, unsigned int d_type, ino_t *ino) | |
148 | { | |
149 | #ifdef CONFIG_AUFS_SHWH | |
150 | return au_ino(sb, bindex, h_ino, d_type, ino); | |
151 | #else | |
152 | return 0; | |
153 | #endif | |
154 | } | |
155 | ||
156 | /* i_op.c */ | |
157 | enum { | |
158 | AuIop_SYMLINK, | |
159 | AuIop_DIR, | |
160 | AuIop_OTHER, | |
161 | AuIop_Last | |
162 | }; | |
163 | extern struct inode_operations aufs_iop[AuIop_Last], | |
164 | aufs_iop_nogetattr[AuIop_Last]; | |
165 | ||
166 | /* au_wr_dir flags */ | |
167 | #define AuWrDir_ADD_ENTRY 1 | |
168 | #define AuWrDir_ISDIR (1 << 1) | |
169 | #define AuWrDir_TMPFILE (1 << 2) | |
170 | #define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) | |
171 | #define au_fset_wrdir(flags, name) \ | |
172 | do { (flags) |= AuWrDir_##name; } while (0) | |
173 | #define au_fclr_wrdir(flags, name) \ | |
174 | do { (flags) &= ~AuWrDir_##name; } while (0) | |
175 | ||
176 | struct au_wr_dir_args { | |
177 | aufs_bindex_t force_btgt; | |
178 | unsigned char flags; | |
179 | }; | |
180 | int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, | |
181 | struct au_wr_dir_args *args); | |
182 | ||
183 | struct dentry *au_pinned_h_parent(struct au_pin *pin); | |
184 | void au_pin_init(struct au_pin *pin, struct dentry *dentry, | |
185 | aufs_bindex_t bindex, int lsc_di, int lsc_hi, | |
186 | unsigned int udba, unsigned char flags); | |
187 | int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, | |
188 | unsigned int udba, unsigned char flags) __must_check; | |
189 | int au_do_pin(struct au_pin *pin) __must_check; | |
190 | void au_unpin(struct au_pin *pin); | |
191 | int au_reval_for_attr(struct dentry *dentry, unsigned int sigen); | |
192 | ||
193 | #define AuIcpup_DID_CPUP 1 | |
194 | #define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name) | |
195 | #define au_fset_icpup(flags, name) \ | |
196 | do { (flags) |= AuIcpup_##name; } while (0) | |
197 | #define au_fclr_icpup(flags, name) \ | |
198 | do { (flags) &= ~AuIcpup_##name; } while (0) | |
199 | ||
200 | struct au_icpup_args { | |
201 | unsigned char flags; | |
202 | unsigned char pin_flags; | |
203 | aufs_bindex_t btgt; | |
204 | unsigned int udba; | |
205 | struct au_pin pin; | |
206 | struct path h_path; | |
207 | struct inode *h_inode; | |
208 | }; | |
209 | ||
210 | int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, | |
211 | struct au_icpup_args *a); | |
212 | ||
213 | int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, | |
214 | int locked); | |
215 | ||
216 | /* i_op_add.c */ | |
217 | int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, | |
218 | struct dentry *h_parent, int isdir); | |
219 | int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, | |
220 | dev_t dev); | |
221 | int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); | |
222 | int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |
223 | bool want_excl); | |
224 | struct vfsub_aopen_args; | |
225 | int au_aopen_or_create(struct inode *dir, struct dentry *dentry, | |
226 | struct vfsub_aopen_args *args); | |
227 | int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); | |
228 | int aufs_link(struct dentry *src_dentry, struct inode *dir, | |
229 | struct dentry *dentry); | |
230 | int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); | |
231 | ||
232 | /* i_op_del.c */ | |
233 | int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); | |
234 | int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, | |
235 | struct dentry *h_parent, int isdir); | |
236 | int aufs_unlink(struct inode *dir, struct dentry *dentry); | |
237 | int aufs_rmdir(struct inode *dir, struct dentry *dentry); | |
238 | ||
239 | /* i_op_ren.c */ | |
240 | int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); | |
241 | int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, | |
242 | struct inode *dir, struct dentry *dentry, | |
243 | unsigned int flags); | |
244 | ||
245 | /* iinfo.c */ | |
246 | struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); | |
247 | void au_hiput(struct au_hinode *hinode); | |
248 | void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, | |
249 | struct dentry *h_wh); | |
250 | unsigned int au_hi_flags(struct inode *inode, int isdir); | |
251 | ||
252 | /* hinode flags */ | |
253 | #define AuHi_XINO 1 | |
254 | #define AuHi_HNOTIFY (1 << 1) | |
255 | #define au_ftest_hi(flags, name) ((flags) & AuHi_##name) | |
256 | #define au_fset_hi(flags, name) \ | |
257 | do { (flags) |= AuHi_##name; } while (0) | |
258 | #define au_fclr_hi(flags, name) \ | |
259 | do { (flags) &= ~AuHi_##name; } while (0) | |
260 | ||
261 | #ifndef CONFIG_AUFS_HNOTIFY | |
262 | #undef AuHi_HNOTIFY | |
263 | #define AuHi_HNOTIFY 0 | |
264 | #endif | |
265 | ||
266 | void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, | |
267 | struct inode *h_inode, unsigned int flags); | |
268 | ||
269 | void au_update_iigen(struct inode *inode, int half); | |
270 | void au_update_ibrange(struct inode *inode, int do_put_zero); | |
271 | ||
272 | void au_icntnr_init_once(void *_c); | |
273 | void au_hinode_init(struct au_hinode *hinode); | |
274 | int au_iinfo_init(struct inode *inode); | |
275 | void au_iinfo_fin(struct inode *inode); | |
276 | int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); | |
277 | ||
278 | #ifdef CONFIG_PROC_FS | |
279 | /* plink.c */ | |
280 | int au_plink_maint(struct super_block *sb, int flags); | |
281 | struct au_sbinfo; | |
282 | void au_plink_maint_leave(struct au_sbinfo *sbinfo); | |
283 | int au_plink_maint_enter(struct super_block *sb); | |
284 | #ifdef CONFIG_AUFS_DEBUG | |
285 | void au_plink_list(struct super_block *sb); | |
286 | #else | |
287 | AuStubVoid(au_plink_list, struct super_block *sb) | |
288 | #endif | |
289 | int au_plink_test(struct inode *inode); | |
290 | struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); | |
291 | void au_plink_append(struct inode *inode, aufs_bindex_t bindex, | |
292 | struct dentry *h_dentry); | |
293 | void au_plink_put(struct super_block *sb, int verbose); | |
294 | void au_plink_clean(struct super_block *sb, int verbose); | |
295 | void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); | |
296 | #else | |
297 | AuStubInt0(au_plink_maint, struct super_block *sb, int flags); | |
298 | AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); | |
299 | AuStubInt0(au_plink_maint_enter, struct super_block *sb); | |
300 | AuStubVoid(au_plink_list, struct super_block *sb); | |
301 | AuStubInt0(au_plink_test, struct inode *inode); | |
302 | AuStub(struct dentry *, au_plink_lkup, return NULL, | |
303 | struct inode *inode, aufs_bindex_t bindex); | |
304 | AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, | |
305 | struct dentry *h_dentry); | |
306 | AuStubVoid(au_plink_put, struct super_block *sb, int verbose); | |
307 | AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); | |
308 | AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); | |
309 | #endif /* CONFIG_PROC_FS */ | |
310 | ||
311 | #ifdef CONFIG_AUFS_XATTR | |
312 | /* xattr.c */ | |
313 | int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, | |
314 | unsigned int verbose); | |
315 | ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); | |
316 | void au_xattr_init(struct super_block *sb); | |
317 | #else | |
318 | AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, | |
319 | int ignore_flags, unsigned int verbose); | |
320 | AuStubVoid(au_xattr_init, struct super_block *sb); | |
321 | #endif | |
322 | ||
323 | #ifdef CONFIG_FS_POSIX_ACL | |
324 | struct posix_acl *aufs_get_acl(struct inode *inode, int type); | |
325 | int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); | |
326 | #endif | |
327 | ||
328 | #if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) | |
329 | enum { | |
330 | AU_XATTR_SET, | |
331 | AU_ACL_SET | |
332 | }; | |
333 | ||
334 | struct au_sxattr { | |
335 | int type; | |
336 | union { | |
337 | struct { | |
338 | const char *name; | |
339 | const void *value; | |
340 | size_t size; | |
341 | int flags; | |
342 | } set; | |
343 | struct { | |
344 | struct posix_acl *acl; | |
345 | int type; | |
346 | } acl_set; | |
347 | } u; | |
348 | }; | |
349 | ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, | |
350 | struct au_sxattr *arg); | |
351 | #endif | |
352 | ||
353 | /* ---------------------------------------------------------------------- */ | |
354 | ||
355 | /* lock subclass for iinfo */ | |
356 | enum { | |
357 | AuLsc_II_CHILD, /* child first */ | |
358 | AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ | |
359 | AuLsc_II_CHILD3, /* copyup dirs */ | |
360 | AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ | |
361 | AuLsc_II_PARENT2, | |
362 | AuLsc_II_PARENT3, /* copyup dirs */ | |
363 | AuLsc_II_NEW_CHILD | |
364 | }; | |
365 | ||
366 | /* | |
367 | * ii_read_lock_child, ii_write_lock_child, | |
368 | * ii_read_lock_child2, ii_write_lock_child2, | |
369 | * ii_read_lock_child3, ii_write_lock_child3, | |
370 | * ii_read_lock_parent, ii_write_lock_parent, | |
371 | * ii_read_lock_parent2, ii_write_lock_parent2, | |
372 | * ii_read_lock_parent3, ii_write_lock_parent3, | |
373 | * ii_read_lock_new_child, ii_write_lock_new_child, | |
374 | */ | |
375 | #define AuReadLockFunc(name, lsc) \ | |
376 | static inline void ii_read_lock_##name(struct inode *i) \ | |
377 | { \ | |
378 | au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ | |
379 | } | |
380 | ||
381 | #define AuWriteLockFunc(name, lsc) \ | |
382 | static inline void ii_write_lock_##name(struct inode *i) \ | |
383 | { \ | |
384 | au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ | |
385 | } | |
386 | ||
387 | #define AuRWLockFuncs(name, lsc) \ | |
388 | AuReadLockFunc(name, lsc) \ | |
389 | AuWriteLockFunc(name, lsc) | |
390 | ||
391 | AuRWLockFuncs(child, CHILD); | |
392 | AuRWLockFuncs(child2, CHILD2); | |
393 | AuRWLockFuncs(child3, CHILD3); | |
394 | AuRWLockFuncs(parent, PARENT); | |
395 | AuRWLockFuncs(parent2, PARENT2); | |
396 | AuRWLockFuncs(parent3, PARENT3); | |
397 | AuRWLockFuncs(new_child, NEW_CHILD); | |
398 | ||
399 | #undef AuReadLockFunc | |
400 | #undef AuWriteLockFunc | |
401 | #undef AuRWLockFuncs | |
402 | ||
403 | /* | |
404 | * ii_read_unlock, ii_write_unlock, ii_downgrade_lock | |
405 | */ | |
406 | AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem); | |
407 | ||
408 | #define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) | |
409 | #define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) | |
410 | #define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) | |
411 | ||
412 | /* ---------------------------------------------------------------------- */ | |
413 | ||
414 | static inline void au_icntnr_init(struct au_icntnr *c) | |
415 | { | |
416 | #ifdef CONFIG_AUFS_DEBUG | |
417 | c->vfs_inode.i_mode = 0; | |
418 | #endif | |
419 | } | |
420 | ||
421 | static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags) | |
422 | { | |
423 | unsigned int gen; | |
424 | struct au_iinfo *iinfo; | |
425 | struct au_iigen *iigen; | |
426 | ||
427 | iinfo = au_ii(inode); | |
428 | iigen = &iinfo->ii_generation; | |
429 | spin_lock(&iigen->ig_spin); | |
430 | if (igflags) | |
431 | *igflags = iigen->ig_flags; | |
432 | gen = iigen->ig_generation; | |
433 | spin_unlock(&iigen->ig_spin); | |
434 | ||
435 | return gen; | |
436 | } | |
437 | ||
438 | /* tiny test for inode number */ | |
439 | /* tmpfs generation is too rough */ | |
440 | static inline int au_test_higen(struct inode *inode, struct inode *h_inode) | |
441 | { | |
442 | struct au_iinfo *iinfo; | |
443 | ||
444 | iinfo = au_ii(inode); | |
445 | AuRwMustAnyLock(&iinfo->ii_rwsem); | |
446 | return !(iinfo->ii_hsb1 == h_inode->i_sb | |
447 | && iinfo->ii_higen == h_inode->i_generation); | |
448 | } | |
449 | ||
450 | static inline void au_iigen_dec(struct inode *inode) | |
451 | { | |
452 | struct au_iinfo *iinfo; | |
453 | struct au_iigen *iigen; | |
454 | ||
455 | iinfo = au_ii(inode); | |
456 | iigen = &iinfo->ii_generation; | |
457 | spin_lock(&iigen->ig_spin); | |
458 | iigen->ig_generation--; | |
459 | spin_unlock(&iigen->ig_spin); | |
460 | } | |
461 | ||
462 | static inline int au_iigen_test(struct inode *inode, unsigned int sigen) | |
463 | { | |
464 | int err; | |
465 | ||
466 | err = 0; | |
467 | if (unlikely(inode && au_iigen(inode, NULL) != sigen)) | |
468 | err = -EIO; | |
469 | ||
470 | return err; | |
471 | } | |
472 | ||
473 | /* ---------------------------------------------------------------------- */ | |
474 | ||
475 | static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, | |
476 | aufs_bindex_t bindex) | |
477 | { | |
478 | return iinfo->ii_hinode + bindex; | |
479 | } | |
480 | ||
481 | static inline int au_is_bad_inode(struct inode *inode) | |
482 | { | |
483 | return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0)); | |
484 | } | |
485 | ||
486 | static inline aufs_bindex_t au_ii_br_id(struct inode *inode, | |
487 | aufs_bindex_t bindex) | |
488 | { | |
489 | IiMustAnyLock(inode); | |
490 | return au_hinode(au_ii(inode), bindex)->hi_id; | |
491 | } | |
492 | ||
493 | static inline aufs_bindex_t au_ibtop(struct inode *inode) | |
494 | { | |
495 | IiMustAnyLock(inode); | |
496 | return au_ii(inode)->ii_btop; | |
497 | } | |
498 | ||
499 | static inline aufs_bindex_t au_ibbot(struct inode *inode) | |
500 | { | |
501 | IiMustAnyLock(inode); | |
502 | return au_ii(inode)->ii_bbot; | |
503 | } | |
504 | ||
505 | static inline struct au_vdir *au_ivdir(struct inode *inode) | |
506 | { | |
507 | IiMustAnyLock(inode); | |
508 | return au_ii(inode)->ii_vdir; | |
509 | } | |
510 | ||
511 | static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) | |
512 | { | |
513 | IiMustAnyLock(inode); | |
514 | return au_hinode(au_ii(inode), bindex)->hi_whdentry; | |
515 | } | |
516 | ||
517 | static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex) | |
518 | { | |
519 | IiMustWriteLock(inode); | |
520 | au_ii(inode)->ii_btop = bindex; | |
521 | } | |
522 | ||
523 | static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex) | |
524 | { | |
525 | IiMustWriteLock(inode); | |
526 | au_ii(inode)->ii_bbot = bindex; | |
527 | } | |
528 | ||
529 | static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) | |
530 | { | |
531 | IiMustWriteLock(inode); | |
532 | au_ii(inode)->ii_vdir = vdir; | |
533 | } | |
534 | ||
535 | static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) | |
536 | { | |
537 | IiMustAnyLock(inode); | |
538 | return au_hinode(au_ii(inode), bindex); | |
539 | } | |
540 | ||
541 | /* ---------------------------------------------------------------------- */ | |
542 | ||
543 | static inline struct dentry *au_pinned_parent(struct au_pin *pin) | |
544 | { | |
545 | if (pin) | |
546 | return pin->parent; | |
547 | return NULL; | |
548 | } | |
549 | ||
550 | static inline struct inode *au_pinned_h_dir(struct au_pin *pin) | |
551 | { | |
552 | if (pin && pin->hdir) | |
553 | return pin->hdir->hi_inode; | |
554 | return NULL; | |
555 | } | |
556 | ||
557 | static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) | |
558 | { | |
559 | if (pin) | |
560 | return pin->hdir; | |
561 | return NULL; | |
562 | } | |
563 | ||
564 | static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) | |
565 | { | |
566 | if (pin) | |
567 | pin->dentry = dentry; | |
568 | } | |
569 | ||
570 | static inline void au_pin_set_parent_lflag(struct au_pin *pin, | |
571 | unsigned char lflag) | |
572 | { | |
573 | if (pin) { | |
574 | if (lflag) | |
575 | au_fset_pin(pin->flags, DI_LOCKED); | |
576 | else | |
577 | au_fclr_pin(pin->flags, DI_LOCKED); | |
578 | } | |
579 | } | |
580 | ||
581 | #if 0 /* reserved */ | |
582 | static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) | |
583 | { | |
584 | if (pin) { | |
585 | dput(pin->parent); | |
586 | pin->parent = dget(parent); | |
587 | } | |
588 | } | |
589 | #endif | |
590 | ||
591 | /* ---------------------------------------------------------------------- */ | |
592 | ||
593 | struct au_branch; | |
594 | #ifdef CONFIG_AUFS_HNOTIFY | |
595 | struct au_hnotify_op { | |
596 | void (*ctl)(struct au_hinode *hinode, int do_set); | |
597 | int (*alloc)(struct au_hinode *hinode); | |
598 | ||
599 | /* | |
600 | * if it returns true, the the caller should free hinode->hi_notify, | |
601 | * otherwise ->free() frees it. | |
602 | */ | |
603 | int (*free)(struct au_hinode *hinode, | |
604 | struct au_hnotify *hn) __must_check; | |
605 | ||
606 | void (*fin)(void); | |
607 | int (*init)(void); | |
608 | ||
609 | int (*reset_br)(unsigned int udba, struct au_branch *br, int perm); | |
610 | void (*fin_br)(struct au_branch *br); | |
611 | int (*init_br)(struct au_branch *br, int perm); | |
612 | }; | |
613 | ||
614 | /* hnotify.c */ | |
615 | int au_hn_alloc(struct au_hinode *hinode, struct inode *inode); | |
616 | void au_hn_free(struct au_hinode *hinode); | |
617 | void au_hn_ctl(struct au_hinode *hinode, int do_set); | |
618 | void au_hn_reset(struct inode *inode, unsigned int flags); | |
619 | int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, | |
620 | struct qstr *h_child_qstr, struct inode *h_child_inode); | |
621 | int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm); | |
622 | int au_hnotify_init_br(struct au_branch *br, int perm); | |
623 | void au_hnotify_fin_br(struct au_branch *br); | |
624 | int __init au_hnotify_init(void); | |
625 | void au_hnotify_fin(void); | |
626 | ||
627 | /* hfsnotify.c */ | |
628 | extern const struct au_hnotify_op au_hnotify_op; | |
629 | ||
630 | static inline | |
631 | void au_hn_init(struct au_hinode *hinode) | |
632 | { | |
633 | hinode->hi_notify = NULL; | |
634 | } | |
635 | ||
636 | static inline struct au_hnotify *au_hn(struct au_hinode *hinode) | |
637 | { | |
638 | return hinode->hi_notify; | |
639 | } | |
640 | ||
641 | #else | |
642 | AuStub(int, au_hn_alloc, return -EOPNOTSUPP, | |
643 | struct au_hinode *hinode __maybe_unused, | |
644 | struct inode *inode __maybe_unused) | |
645 | AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode) | |
646 | AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) | |
647 | AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, | |
648 | int do_set __maybe_unused) | |
649 | AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, | |
650 | unsigned int flags __maybe_unused) | |
651 | AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused, | |
652 | struct au_branch *br __maybe_unused, | |
653 | int perm __maybe_unused) | |
654 | AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused, | |
655 | int perm __maybe_unused) | |
656 | AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused) | |
657 | AuStubInt0(__init au_hnotify_init, void) | |
658 | AuStubVoid(au_hnotify_fin, void) | |
659 | AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) | |
660 | #endif /* CONFIG_AUFS_HNOTIFY */ | |
661 | ||
662 | static inline void au_hn_suspend(struct au_hinode *hdir) | |
663 | { | |
664 | au_hn_ctl(hdir, /*do_set*/0); | |
665 | } | |
666 | ||
667 | static inline void au_hn_resume(struct au_hinode *hdir) | |
668 | { | |
669 | au_hn_ctl(hdir, /*do_set*/1); | |
670 | } | |
671 | ||
672 | static inline void au_hn_inode_lock(struct au_hinode *hdir) | |
673 | { | |
674 | inode_lock(hdir->hi_inode); | |
675 | au_hn_suspend(hdir); | |
676 | } | |
677 | ||
678 | static inline void au_hn_inode_lock_nested(struct au_hinode *hdir, | |
679 | unsigned int sc __maybe_unused) | |
680 | { | |
681 | inode_lock_nested(hdir->hi_inode, sc); | |
682 | au_hn_suspend(hdir); | |
683 | } | |
684 | ||
685 | static inline void au_hn_inode_unlock(struct au_hinode *hdir) | |
686 | { | |
687 | au_hn_resume(hdir); | |
688 | inode_unlock(hdir->hi_inode); | |
689 | } | |
690 | ||
691 | #endif /* __KERNEL__ */ | |
692 | #endif /* __AUFS_INODE_H__ */ |