2 * Copyright (C) 2005-2016 Junjiro R. Okajima
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.
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.
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/>.
19 * lookup and dentry operations
22 #ifndef __AUFS_DENTRY_H__
23 #define __AUFS_DENTRY_H__
27 #include <linux/dcache.h>
31 struct dentry
*hd_dentry
;
36 atomic_t di_generation
;
38 struct au_rwsem di_rwsem
;
39 aufs_bindex_t di_btop
, di_bbot
, di_bwh
, di_bdiropq
;
40 unsigned char di_tmpfile
; /* to allow the different name */
42 struct au_hdentry
*di_hdentry
;
43 struct llist_node di_lnode
; /* delayed free */
45 } ____cacheline_aligned_in_smp
;
47 /* ---------------------------------------------------------------------- */
49 /* flags for au_lkup_dentry() */
50 #define AuLkup_ALLOW_NEG 1
51 #define AuLkup_IGNORE_PERM (1 << 1)
52 #define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
53 #define au_fset_lkup(flags, name) \
54 do { (flags) |= AuLkup_##name; } while (0)
55 #define au_fclr_lkup(flags, name) \
56 do { (flags) &= ~AuLkup_##name; } while (0)
58 /* ---------------------------------------------------------------------- */
61 extern const struct dentry_operations aufs_dop
, aufs_dop_noreval
;
63 struct dentry
*au_sio_lkup_one(struct qstr
*name
, struct dentry
*parent
);
64 int au_h_verify(struct dentry
*h_dentry
, unsigned int udba
, struct inode
*h_dir
,
65 struct dentry
*h_parent
, struct au_branch
*br
);
67 int au_lkup_dentry(struct dentry
*dentry
, aufs_bindex_t btop
,
69 int au_lkup_neg(struct dentry
*dentry
, aufs_bindex_t bindex
, int wh
);
70 int au_refresh_dentry(struct dentry
*dentry
, struct dentry
*parent
);
71 int au_reval_dpath(struct dentry
*dentry
, unsigned int sigen
);
72 void au_refresh_dop(struct dentry
*dentry
, int force_reval
);
75 void au_di_init_once(void *_di
);
76 struct au_dinfo
*au_di_alloc(struct super_block
*sb
, unsigned int lsc
);
77 void au_di_free(struct au_dinfo
*dinfo
);
78 void au_di_swap(struct au_dinfo
*a
, struct au_dinfo
*b
);
79 void au_di_cp(struct au_dinfo
*dst
, struct au_dinfo
*src
);
80 int au_di_init(struct dentry
*dentry
);
81 void au_di_fin(struct dentry
*dentry
);
82 int au_di_realloc(struct au_dinfo
*dinfo
, int nbr
, int may_shrink
);
84 void di_read_lock(struct dentry
*d
, int flags
, unsigned int lsc
);
85 void di_read_unlock(struct dentry
*d
, int flags
);
86 void di_downgrade_lock(struct dentry
*d
, int flags
);
87 void di_write_lock(struct dentry
*d
, unsigned int lsc
);
88 void di_write_unlock(struct dentry
*d
);
89 void di_write_lock2_child(struct dentry
*d1
, struct dentry
*d2
, int isdir
);
90 void di_write_lock2_parent(struct dentry
*d1
, struct dentry
*d2
, int isdir
);
91 void di_write_unlock2(struct dentry
*d1
, struct dentry
*d2
);
93 struct dentry
*au_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
);
94 struct dentry
*au_h_d_alias(struct dentry
*dentry
, aufs_bindex_t bindex
);
95 aufs_bindex_t
au_dbtail(struct dentry
*dentry
);
96 aufs_bindex_t
au_dbtaildir(struct dentry
*dentry
);
98 void au_set_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
,
99 struct dentry
*h_dentry
);
100 int au_digen_test(struct dentry
*dentry
, unsigned int sigen
);
101 int au_dbrange_test(struct dentry
*dentry
);
102 void au_update_digen(struct dentry
*dentry
);
103 void au_update_dbrange(struct dentry
*dentry
, int do_put_zero
);
104 void au_update_dbtop(struct dentry
*dentry
);
105 void au_update_dbbot(struct dentry
*dentry
);
106 int au_find_dbindex(struct dentry
*dentry
, struct dentry
*h_dentry
);
108 /* ---------------------------------------------------------------------- */
110 static inline struct au_dinfo
*au_di(struct dentry
*dentry
)
112 return dentry
->d_fsdata
;
115 /* ---------------------------------------------------------------------- */
117 /* lock subclass for dinfo */
119 AuLsc_DI_CHILD
, /* child first */
120 AuLsc_DI_CHILD2
, /* rename(2), link(2), and cpup at hnotify */
121 AuLsc_DI_CHILD3
, /* copyup dirs */
125 AuLsc_DI_TMP
/* temp for replacing dinfo */
129 * di_read_lock_child, di_write_lock_child,
130 * di_read_lock_child2, di_write_lock_child2,
131 * di_read_lock_child3, di_write_lock_child3,
132 * di_read_lock_parent, di_write_lock_parent,
133 * di_read_lock_parent2, di_write_lock_parent2,
134 * di_read_lock_parent3, di_write_lock_parent3,
136 #define AuReadLockFunc(name, lsc) \
137 static inline void di_read_lock_##name(struct dentry *d, int flags) \
138 { di_read_lock(d, flags, AuLsc_DI_##lsc); }
140 #define AuWriteLockFunc(name, lsc) \
141 static inline void di_write_lock_##name(struct dentry *d) \
142 { di_write_lock(d, AuLsc_DI_##lsc); }
144 #define AuRWLockFuncs(name, lsc) \
145 AuReadLockFunc(name, lsc) \
146 AuWriteLockFunc(name, lsc)
148 AuRWLockFuncs(child
, CHILD
);
149 AuRWLockFuncs(child2
, CHILD2
);
150 AuRWLockFuncs(child3
, CHILD3
);
151 AuRWLockFuncs(parent
, PARENT
);
152 AuRWLockFuncs(parent2
, PARENT2
);
153 AuRWLockFuncs(parent3
, PARENT3
);
155 #undef AuReadLockFunc
156 #undef AuWriteLockFunc
159 #define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
160 #define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
161 #define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
163 /* ---------------------------------------------------------------------- */
165 /* todo: memory barrier? */
166 static inline unsigned int au_digen(struct dentry
*d
)
168 return atomic_read(&au_di(d
)->di_generation
);
171 static inline void au_h_dentry_init(struct au_hdentry
*hdentry
)
173 hdentry
->hd_dentry
= NULL
;
176 static inline struct au_hdentry
*au_hdentry(struct au_dinfo
*di
,
177 aufs_bindex_t bindex
)
179 return di
->di_hdentry
+ bindex
;
182 static inline void au_hdput(struct au_hdentry
*hd
)
188 static inline aufs_bindex_t
au_dbtop(struct dentry
*dentry
)
190 DiMustAnyLock(dentry
);
191 return au_di(dentry
)->di_btop
;
194 static inline aufs_bindex_t
au_dbbot(struct dentry
*dentry
)
196 DiMustAnyLock(dentry
);
197 return au_di(dentry
)->di_bbot
;
200 static inline aufs_bindex_t
au_dbwh(struct dentry
*dentry
)
202 DiMustAnyLock(dentry
);
203 return au_di(dentry
)->di_bwh
;
206 static inline aufs_bindex_t
au_dbdiropq(struct dentry
*dentry
)
208 DiMustAnyLock(dentry
);
209 return au_di(dentry
)->di_bdiropq
;
212 /* todo: hard/soft set? */
213 static inline void au_set_dbtop(struct dentry
*dentry
, aufs_bindex_t bindex
)
215 DiMustWriteLock(dentry
);
216 au_di(dentry
)->di_btop
= bindex
;
219 static inline void au_set_dbbot(struct dentry
*dentry
, aufs_bindex_t bindex
)
221 DiMustWriteLock(dentry
);
222 au_di(dentry
)->di_bbot
= bindex
;
225 static inline void au_set_dbwh(struct dentry
*dentry
, aufs_bindex_t bindex
)
227 DiMustWriteLock(dentry
);
228 /* dbwh can be outside of btop - bbot range */
229 au_di(dentry
)->di_bwh
= bindex
;
232 static inline void au_set_dbdiropq(struct dentry
*dentry
, aufs_bindex_t bindex
)
234 DiMustWriteLock(dentry
);
235 au_di(dentry
)->di_bdiropq
= bindex
;
238 /* ---------------------------------------------------------------------- */
240 #ifdef CONFIG_AUFS_HNOTIFY
241 static inline void au_digen_dec(struct dentry
*d
)
243 atomic_dec(&au_di(d
)->di_generation
);
246 static inline void au_hn_di_reinit(struct dentry
*dentry
)
248 dentry
->d_fsdata
= NULL
;
251 AuStubVoid(au_hn_di_reinit
, struct dentry
*dentry __maybe_unused
)
252 #endif /* CONFIG_AUFS_HNOTIFY */
254 #endif /* __KERNEL__ */
255 #endif /* __AUFS_DENTRY_H__ */