]>
Commit | Line | Data |
---|---|---|
5b88fdd9 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 | ||
215 | /* i_op_add.c */ | |
216 | int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, | |
217 | struct dentry *h_parent, int isdir); | |
218 | int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, | |
219 | dev_t dev); | |
220 | int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); | |
221 | int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |
222 | bool want_excl); | |
223 | struct vfsub_aopen_args; | |
224 | int au_aopen_or_create(struct inode *dir, struct dentry *dentry, | |
225 | struct vfsub_aopen_args *args); | |
226 | int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); | |
227 | int aufs_link(struct dentry *src_dentry, struct inode *dir, | |
228 | struct dentry *dentry); | |
229 | int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); | |
230 | ||
231 | /* i_op_del.c */ | |
232 | int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); | |
233 | int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, | |
234 | struct dentry *h_parent, int isdir); | |
235 | int aufs_unlink(struct inode *dir, struct dentry *dentry); | |
236 | int aufs_rmdir(struct inode *dir, struct dentry *dentry); | |
237 | ||
238 | /* i_op_ren.c */ | |
239 | int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); | |
240 | int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, | |
241 | struct inode *dir, struct dentry *dentry); | |
242 | ||
243 | /* iinfo.c */ | |
244 | struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); | |
245 | void au_hiput(struct au_hinode *hinode); | |
246 | void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, | |
247 | struct dentry *h_wh); | |
248 | unsigned int au_hi_flags(struct inode *inode, int isdir); | |
249 | ||
250 | /* hinode flags */ | |
251 | #define AuHi_XINO 1 | |
252 | #define AuHi_HNOTIFY (1 << 1) | |
253 | #define au_ftest_hi(flags, name) ((flags) & AuHi_##name) | |
254 | #define au_fset_hi(flags, name) \ | |
255 | do { (flags) |= AuHi_##name; } while (0) | |
256 | #define au_fclr_hi(flags, name) \ | |
257 | do { (flags) &= ~AuHi_##name; } while (0) | |
258 | ||
259 | #ifndef CONFIG_AUFS_HNOTIFY | |
260 | #undef AuHi_HNOTIFY | |
261 | #define AuHi_HNOTIFY 0 | |
262 | #endif | |
263 | ||
264 | void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, | |
265 | struct inode *h_inode, unsigned int flags); | |
266 | ||
267 | void au_update_iigen(struct inode *inode, int half); | |
268 | void au_update_ibrange(struct inode *inode, int do_put_zero); | |
269 | ||
270 | void au_icntnr_init_once(void *_c); | |
271 | void au_hinode_init(struct au_hinode *hinode); | |
272 | int au_iinfo_init(struct inode *inode); | |
273 | void au_iinfo_fin(struct inode *inode); | |
274 | int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); | |
275 | ||
276 | #ifdef CONFIG_PROC_FS | |
277 | /* plink.c */ | |
278 | int au_plink_maint(struct super_block *sb, int flags); | |
279 | struct au_sbinfo; | |
280 | void au_plink_maint_leave(struct au_sbinfo *sbinfo); | |
281 | int au_plink_maint_enter(struct super_block *sb); | |
282 | #ifdef CONFIG_AUFS_DEBUG | |
283 | void au_plink_list(struct super_block *sb); | |
284 | #else | |
285 | AuStubVoid(au_plink_list, struct super_block *sb) | |
286 | #endif | |
287 | int au_plink_test(struct inode *inode); | |
288 | struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); | |
289 | void au_plink_append(struct inode *inode, aufs_bindex_t bindex, | |
290 | struct dentry *h_dentry); | |
291 | void au_plink_put(struct super_block *sb, int verbose); | |
292 | void au_plink_clean(struct super_block *sb, int verbose); | |
293 | void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); | |
294 | #else | |
295 | AuStubInt0(au_plink_maint, struct super_block *sb, int flags); | |
296 | AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); | |
297 | AuStubInt0(au_plink_maint_enter, struct super_block *sb); | |
298 | AuStubVoid(au_plink_list, struct super_block *sb); | |
299 | AuStubInt0(au_plink_test, struct inode *inode); | |
300 | AuStub(struct dentry *, au_plink_lkup, return NULL, | |
301 | struct inode *inode, aufs_bindex_t bindex); | |
302 | AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, | |
303 | struct dentry *h_dentry); | |
304 | AuStubVoid(au_plink_put, struct super_block *sb, int verbose); | |
305 | AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); | |
306 | AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); | |
307 | #endif /* CONFIG_PROC_FS */ | |
308 | ||
309 | #ifdef CONFIG_AUFS_XATTR | |
310 | /* xattr.c */ | |
311 | int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, | |
312 | unsigned int verbose); | |
313 | ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); | |
caaa92e7 | 314 | void au_xattr_init(struct super_block *sb); |
5b88fdd9 SF |
315 | #else |
316 | AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, | |
317 | int ignore_flags, unsigned int verbose); | |
caaa92e7 | 318 | AuStubVoid(au_xattr_init, struct super_block *sb); |
5b88fdd9 SF |
319 | #endif |
320 | ||
321 | #ifdef CONFIG_FS_POSIX_ACL | |
322 | struct posix_acl *aufs_get_acl(struct inode *inode, int type); | |
323 | int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); | |
324 | #endif | |
325 | ||
326 | #if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) | |
327 | enum { | |
328 | AU_XATTR_SET, | |
329 | AU_XATTR_REMOVE, | |
330 | AU_ACL_SET | |
331 | }; | |
332 | ||
333 | struct au_srxattr { | |
334 | int type; | |
335 | union { | |
336 | struct { | |
337 | const char *name; | |
338 | const void *value; | |
339 | size_t size; | |
340 | int flags; | |
341 | } set; | |
342 | struct { | |
343 | const char *name; | |
344 | } remove; | |
345 | struct { | |
346 | struct posix_acl *acl; | |
347 | int type; | |
348 | } acl_set; | |
349 | } u; | |
350 | }; | |
351 | ssize_t au_srxattr(struct dentry *dentry, struct inode *inode, | |
352 | struct au_srxattr *arg); | |
353 | #endif | |
354 | ||
355 | /* ---------------------------------------------------------------------- */ | |
356 | ||
357 | /* lock subclass for iinfo */ | |
358 | enum { | |
359 | AuLsc_II_CHILD, /* child first */ | |
360 | AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ | |
361 | AuLsc_II_CHILD3, /* copyup dirs */ | |
362 | AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ | |
363 | AuLsc_II_PARENT2, | |
364 | AuLsc_II_PARENT3, /* copyup dirs */ | |
365 | AuLsc_II_NEW_CHILD | |
366 | }; | |
367 | ||
368 | /* | |
369 | * ii_read_lock_child, ii_write_lock_child, | |
370 | * ii_read_lock_child2, ii_write_lock_child2, | |
371 | * ii_read_lock_child3, ii_write_lock_child3, | |
372 | * ii_read_lock_parent, ii_write_lock_parent, | |
373 | * ii_read_lock_parent2, ii_write_lock_parent2, | |
374 | * ii_read_lock_parent3, ii_write_lock_parent3, | |
375 | * ii_read_lock_new_child, ii_write_lock_new_child, | |
376 | */ | |
377 | #define AuReadLockFunc(name, lsc) \ | |
378 | static inline void ii_read_lock_##name(struct inode *i) \ | |
379 | { \ | |
380 | au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ | |
381 | } | |
382 | ||
383 | #define AuWriteLockFunc(name, lsc) \ | |
384 | static inline void ii_write_lock_##name(struct inode *i) \ | |
385 | { \ | |
386 | au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ | |
387 | } | |
388 | ||
389 | #define AuRWLockFuncs(name, lsc) \ | |
390 | AuReadLockFunc(name, lsc) \ | |
391 | AuWriteLockFunc(name, lsc) | |
392 | ||
393 | AuRWLockFuncs(child, CHILD); | |
394 | AuRWLockFuncs(child2, CHILD2); | |
395 | AuRWLockFuncs(child3, CHILD3); | |
396 | AuRWLockFuncs(parent, PARENT); | |
397 | AuRWLockFuncs(parent2, PARENT2); | |
398 | AuRWLockFuncs(parent3, PARENT3); | |
399 | AuRWLockFuncs(new_child, NEW_CHILD); | |
400 | ||
401 | #undef AuReadLockFunc | |
402 | #undef AuWriteLockFunc | |
403 | #undef AuRWLockFuncs | |
404 | ||
405 | /* | |
406 | * ii_read_unlock, ii_write_unlock, ii_downgrade_lock | |
407 | */ | |
408 | AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem); | |
409 | ||
410 | #define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) | |
411 | #define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) | |
412 | #define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) | |
413 | ||
414 | /* ---------------------------------------------------------------------- */ | |
415 | ||
416 | static inline void au_icntnr_init(struct au_icntnr *c) | |
417 | { | |
418 | #ifdef CONFIG_AUFS_DEBUG | |
419 | c->vfs_inode.i_mode = 0; | |
420 | #endif | |
421 | } | |
422 | ||
423 | static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags) | |
424 | { | |
425 | unsigned int gen; | |
426 | struct au_iinfo *iinfo; | |
427 | struct au_iigen *iigen; | |
428 | ||
429 | iinfo = au_ii(inode); | |
430 | iigen = &iinfo->ii_generation; | |
431 | spin_lock(&iigen->ig_spin); | |
432 | if (igflags) | |
433 | *igflags = iigen->ig_flags; | |
434 | gen = iigen->ig_generation; | |
435 | spin_unlock(&iigen->ig_spin); | |
436 | ||
437 | return gen; | |
438 | } | |
439 | ||
440 | /* tiny test for inode number */ | |
441 | /* tmpfs generation is too rough */ | |
442 | static inline int au_test_higen(struct inode *inode, struct inode *h_inode) | |
443 | { | |
444 | struct au_iinfo *iinfo; | |
445 | ||
446 | iinfo = au_ii(inode); | |
447 | AuRwMustAnyLock(&iinfo->ii_rwsem); | |
448 | return !(iinfo->ii_hsb1 == h_inode->i_sb | |
449 | && iinfo->ii_higen == h_inode->i_generation); | |
450 | } | |
451 | ||
452 | static inline void au_iigen_dec(struct inode *inode) | |
453 | { | |
454 | struct au_iinfo *iinfo; | |
455 | struct au_iigen *iigen; | |
456 | ||
457 | iinfo = au_ii(inode); | |
458 | iigen = &iinfo->ii_generation; | |
459 | spin_lock(&iigen->ig_spin); | |
460 | iigen->ig_generation--; | |
461 | spin_unlock(&iigen->ig_spin); | |
462 | } | |
463 | ||
464 | static inline int au_iigen_test(struct inode *inode, unsigned int sigen) | |
465 | { | |
466 | int err; | |
467 | ||
468 | err = 0; | |
469 | if (unlikely(inode && au_iigen(inode, NULL) != sigen)) | |
470 | err = -EIO; | |
471 | ||
472 | return err; | |
473 | } | |
474 | ||
475 | /* ---------------------------------------------------------------------- */ | |
476 | ||
477 | static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, | |
478 | aufs_bindex_t bindex) | |
479 | { | |
480 | return iinfo->ii_hinode + bindex; | |
481 | } | |
482 | ||
483 | static inline int au_is_bad_inode(struct inode *inode) | |
484 | { | |
485 | return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0)); | |
486 | } | |
487 | ||
488 | static inline aufs_bindex_t au_ii_br_id(struct inode *inode, | |
489 | aufs_bindex_t bindex) | |
490 | { | |
491 | IiMustAnyLock(inode); | |
492 | return au_hinode(au_ii(inode), bindex)->hi_id; | |
493 | } | |
494 | ||
495 | static inline aufs_bindex_t au_ibtop(struct inode *inode) | |
496 | { | |
497 | IiMustAnyLock(inode); | |
498 | return au_ii(inode)->ii_btop; | |
499 | } | |
500 | ||
501 | static inline aufs_bindex_t au_ibbot(struct inode *inode) | |
502 | { | |
503 | IiMustAnyLock(inode); | |
504 | return au_ii(inode)->ii_bbot; | |
505 | } | |
506 | ||
507 | static inline struct au_vdir *au_ivdir(struct inode *inode) | |
508 | { | |
509 | IiMustAnyLock(inode); | |
510 | return au_ii(inode)->ii_vdir; | |
511 | } | |
512 | ||
513 | static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) | |
514 | { | |
515 | IiMustAnyLock(inode); | |
516 | return au_hinode(au_ii(inode), bindex)->hi_whdentry; | |
517 | } | |
518 | ||
519 | static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex) | |
520 | { | |
521 | IiMustWriteLock(inode); | |
522 | au_ii(inode)->ii_btop = bindex; | |
523 | } | |
524 | ||
525 | static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex) | |
526 | { | |
527 | IiMustWriteLock(inode); | |
528 | au_ii(inode)->ii_bbot = bindex; | |
529 | } | |
530 | ||
531 | static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) | |
532 | { | |
533 | IiMustWriteLock(inode); | |
534 | au_ii(inode)->ii_vdir = vdir; | |
535 | } | |
536 | ||
537 | static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) | |
538 | { | |
539 | IiMustAnyLock(inode); | |
540 | return au_hinode(au_ii(inode), bindex); | |
541 | } | |
542 | ||
543 | /* ---------------------------------------------------------------------- */ | |
544 | ||
545 | static inline struct dentry *au_pinned_parent(struct au_pin *pin) | |
546 | { | |
547 | if (pin) | |
548 | return pin->parent; | |
549 | return NULL; | |
550 | } | |
551 | ||
552 | static inline struct inode *au_pinned_h_dir(struct au_pin *pin) | |
553 | { | |
554 | if (pin && pin->hdir) | |
555 | return pin->hdir->hi_inode; | |
556 | return NULL; | |
557 | } | |
558 | ||
559 | static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) | |
560 | { | |
561 | if (pin) | |
562 | return pin->hdir; | |
563 | return NULL; | |
564 | } | |
565 | ||
566 | static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) | |
567 | { | |
568 | if (pin) | |
569 | pin->dentry = dentry; | |
570 | } | |
571 | ||
572 | static inline void au_pin_set_parent_lflag(struct au_pin *pin, | |
573 | unsigned char lflag) | |
574 | { | |
575 | if (pin) { | |
576 | if (lflag) | |
577 | au_fset_pin(pin->flags, DI_LOCKED); | |
578 | else | |
579 | au_fclr_pin(pin->flags, DI_LOCKED); | |
580 | } | |
581 | } | |
582 | ||
583 | #if 0 /* reserved */ | |
584 | static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) | |
585 | { | |
586 | if (pin) { | |
587 | dput(pin->parent); | |
588 | pin->parent = dget(parent); | |
589 | } | |
590 | } | |
591 | #endif | |
592 | ||
593 | /* ---------------------------------------------------------------------- */ | |
594 | ||
595 | struct au_branch; | |
596 | #ifdef CONFIG_AUFS_HNOTIFY | |
597 | struct au_hnotify_op { | |
598 | void (*ctl)(struct au_hinode *hinode, int do_set); | |
599 | int (*alloc)(struct au_hinode *hinode); | |
600 | ||
601 | /* | |
602 | * if it returns true, the the caller should free hinode->hi_notify, | |
603 | * otherwise ->free() frees it. | |
604 | */ | |
605 | int (*free)(struct au_hinode *hinode, | |
606 | struct au_hnotify *hn) __must_check; | |
607 | ||
608 | void (*fin)(void); | |
609 | int (*init)(void); | |
610 | ||
611 | int (*reset_br)(unsigned int udba, struct au_branch *br, int perm); | |
612 | void (*fin_br)(struct au_branch *br); | |
613 | int (*init_br)(struct au_branch *br, int perm); | |
614 | }; | |
615 | ||
616 | /* hnotify.c */ | |
617 | int au_hn_alloc(struct au_hinode *hinode, struct inode *inode); | |
618 | void au_hn_free(struct au_hinode *hinode); | |
619 | void au_hn_ctl(struct au_hinode *hinode, int do_set); | |
620 | void au_hn_reset(struct inode *inode, unsigned int flags); | |
621 | int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, | |
622 | struct qstr *h_child_qstr, struct inode *h_child_inode); | |
623 | int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm); | |
624 | int au_hnotify_init_br(struct au_branch *br, int perm); | |
625 | void au_hnotify_fin_br(struct au_branch *br); | |
626 | int __init au_hnotify_init(void); | |
627 | void au_hnotify_fin(void); | |
628 | ||
629 | /* hfsnotify.c */ | |
630 | extern const struct au_hnotify_op au_hnotify_op; | |
631 | ||
632 | static inline | |
633 | void au_hn_init(struct au_hinode *hinode) | |
634 | { | |
635 | hinode->hi_notify = NULL; | |
636 | } | |
637 | ||
638 | static inline struct au_hnotify *au_hn(struct au_hinode *hinode) | |
639 | { | |
640 | return hinode->hi_notify; | |
641 | } | |
642 | ||
643 | #else | |
644 | AuStub(int, au_hn_alloc, return -EOPNOTSUPP, | |
645 | struct au_hinode *hinode __maybe_unused, | |
646 | struct inode *inode __maybe_unused) | |
647 | AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode) | |
648 | AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) | |
649 | AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, | |
650 | int do_set __maybe_unused) | |
651 | AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, | |
652 | unsigned int flags __maybe_unused) | |
653 | AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused, | |
654 | struct au_branch *br __maybe_unused, | |
655 | int perm __maybe_unused) | |
656 | AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused, | |
657 | int perm __maybe_unused) | |
658 | AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused) | |
659 | AuStubInt0(__init au_hnotify_init, void) | |
660 | AuStubVoid(au_hnotify_fin, void) | |
661 | AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) | |
662 | #endif /* CONFIG_AUFS_HNOTIFY */ | |
663 | ||
664 | static inline void au_hn_suspend(struct au_hinode *hdir) | |
665 | { | |
666 | au_hn_ctl(hdir, /*do_set*/0); | |
667 | } | |
668 | ||
669 | static inline void au_hn_resume(struct au_hinode *hdir) | |
670 | { | |
671 | au_hn_ctl(hdir, /*do_set*/1); | |
672 | } | |
673 | ||
674 | static inline void au_hn_inode_lock(struct au_hinode *hdir) | |
675 | { | |
676 | inode_lock(hdir->hi_inode); | |
677 | au_hn_suspend(hdir); | |
678 | } | |
679 | ||
680 | static inline void au_hn_inode_lock_nested(struct au_hinode *hdir, | |
681 | unsigned int sc __maybe_unused) | |
682 | { | |
683 | inode_lock_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__ */ |