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