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