2 * Copyright (C) 2005-2017 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 */
41 struct au_hdentry
*di_hdentry
;
42 } ____cacheline_aligned_in_smp
;
44 /* ---------------------------------------------------------------------- */
46 /* flags for au_lkup_dentry() */
47 #define AuLkup_ALLOW_NEG 1
48 #define AuLkup_IGNORE_PERM (1 << 1)
49 #define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
50 #define au_fset_lkup(flags, name) \
51 do { (flags) |= AuLkup_##name; } while (0)
52 #define au_fclr_lkup(flags, name) \
53 do { (flags) &= ~AuLkup_##name; } while (0)
55 /* ---------------------------------------------------------------------- */
58 extern const struct dentry_operations aufs_dop
, aufs_dop_noreval
;
60 struct dentry
*au_sio_lkup_one(struct qstr
*name
, struct dentry
*parent
);
61 int au_h_verify(struct dentry
*h_dentry
, unsigned int udba
, struct inode
*h_dir
,
62 struct dentry
*h_parent
, struct au_branch
*br
);
64 int au_lkup_dentry(struct dentry
*dentry
, aufs_bindex_t btop
,
66 int au_lkup_neg(struct dentry
*dentry
, aufs_bindex_t bindex
, int wh
);
67 int au_refresh_dentry(struct dentry
*dentry
, struct dentry
*parent
);
68 int au_reval_dpath(struct dentry
*dentry
, unsigned int sigen
);
69 void au_refresh_dop(struct dentry
*dentry
, int force_reval
);
72 void au_di_init_once(void *_di
);
73 struct au_dinfo
*au_di_alloc(struct super_block
*sb
, unsigned int lsc
);
74 void au_di_free(struct au_dinfo
*dinfo
);
75 void au_di_swap(struct au_dinfo
*a
, struct au_dinfo
*b
);
76 void au_di_cp(struct au_dinfo
*dst
, struct au_dinfo
*src
);
77 int au_di_init(struct dentry
*dentry
);
78 void au_di_fin(struct dentry
*dentry
);
79 int au_di_realloc(struct au_dinfo
*dinfo
, int nbr
, int may_shrink
);
81 void di_read_lock(struct dentry
*d
, int flags
, unsigned int lsc
);
82 void di_read_unlock(struct dentry
*d
, int flags
);
83 void di_downgrade_lock(struct dentry
*d
, int flags
);
84 void di_write_lock(struct dentry
*d
, unsigned int lsc
);
85 void di_write_unlock(struct dentry
*d
);
86 void di_write_lock2_child(struct dentry
*d1
, struct dentry
*d2
, int isdir
);
87 void di_write_lock2_parent(struct dentry
*d1
, struct dentry
*d2
, int isdir
);
88 void di_write_unlock2(struct dentry
*d1
, struct dentry
*d2
);
90 struct dentry
*au_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
);
91 struct dentry
*au_h_d_alias(struct dentry
*dentry
, aufs_bindex_t bindex
);
92 aufs_bindex_t
au_dbtail(struct dentry
*dentry
);
93 aufs_bindex_t
au_dbtaildir(struct dentry
*dentry
);
95 void au_set_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
,
96 struct dentry
*h_dentry
);
97 int au_digen_test(struct dentry
*dentry
, unsigned int sigen
);
98 int au_dbrange_test(struct dentry
*dentry
);
99 void au_update_digen(struct dentry
*dentry
);
100 void au_update_dbrange(struct dentry
*dentry
, int do_put_zero
);
101 void au_update_dbtop(struct dentry
*dentry
);
102 void au_update_dbbot(struct dentry
*dentry
);
103 int au_find_dbindex(struct dentry
*dentry
, struct dentry
*h_dentry
);
105 /* ---------------------------------------------------------------------- */
107 static inline struct au_dinfo
*au_di(struct dentry
*dentry
)
109 return dentry
->d_fsdata
;
112 /* ---------------------------------------------------------------------- */
114 /* lock subclass for dinfo */
116 AuLsc_DI_CHILD
, /* child first */
117 AuLsc_DI_CHILD2
, /* rename(2), link(2), and cpup at hnotify */
118 AuLsc_DI_CHILD3
, /* copyup dirs */
122 AuLsc_DI_TMP
/* temp for replacing dinfo */
126 * di_read_lock_child, di_write_lock_child,
127 * di_read_lock_child2, di_write_lock_child2,
128 * di_read_lock_child3, di_write_lock_child3,
129 * di_read_lock_parent, di_write_lock_parent,
130 * di_read_lock_parent2, di_write_lock_parent2,
131 * di_read_lock_parent3, di_write_lock_parent3,
133 #define AuReadLockFunc(name, lsc) \
134 static inline void di_read_lock_##name(struct dentry *d, int flags) \
135 { di_read_lock(d, flags, AuLsc_DI_##lsc); }
137 #define AuWriteLockFunc(name, lsc) \
138 static inline void di_write_lock_##name(struct dentry *d) \
139 { di_write_lock(d, AuLsc_DI_##lsc); }
141 #define AuRWLockFuncs(name, lsc) \
142 AuReadLockFunc(name, lsc) \
143 AuWriteLockFunc(name, lsc)
145 AuRWLockFuncs(child
, CHILD
);
146 AuRWLockFuncs(child2
, CHILD2
);
147 AuRWLockFuncs(child3
, CHILD3
);
148 AuRWLockFuncs(parent
, PARENT
);
149 AuRWLockFuncs(parent2
, PARENT2
);
150 AuRWLockFuncs(parent3
, PARENT3
);
152 #undef AuReadLockFunc
153 #undef AuWriteLockFunc
156 #define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
157 #define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
158 #define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
160 /* ---------------------------------------------------------------------- */
162 /* todo: memory barrier? */
163 static inline unsigned int au_digen(struct dentry
*d
)
165 return atomic_read(&au_di(d
)->di_generation
);
168 static inline void au_h_dentry_init(struct au_hdentry
*hdentry
)
170 hdentry
->hd_dentry
= NULL
;
173 static inline struct au_hdentry
*au_hdentry(struct au_dinfo
*di
,
174 aufs_bindex_t bindex
)
176 return di
->di_hdentry
+ bindex
;
179 static inline void au_hdput(struct au_hdentry
*hd
)
185 static inline aufs_bindex_t
au_dbtop(struct dentry
*dentry
)
187 DiMustAnyLock(dentry
);
188 return au_di(dentry
)->di_btop
;
191 static inline aufs_bindex_t
au_dbbot(struct dentry
*dentry
)
193 DiMustAnyLock(dentry
);
194 return au_di(dentry
)->di_bbot
;
197 static inline aufs_bindex_t
au_dbwh(struct dentry
*dentry
)
199 DiMustAnyLock(dentry
);
200 return au_di(dentry
)->di_bwh
;
203 static inline aufs_bindex_t
au_dbdiropq(struct dentry
*dentry
)
205 DiMustAnyLock(dentry
);
206 return au_di(dentry
)->di_bdiropq
;
209 /* todo: hard/soft set? */
210 static inline void au_set_dbtop(struct dentry
*dentry
, aufs_bindex_t bindex
)
212 DiMustWriteLock(dentry
);
213 au_di(dentry
)->di_btop
= bindex
;
216 static inline void au_set_dbbot(struct dentry
*dentry
, aufs_bindex_t bindex
)
218 DiMustWriteLock(dentry
);
219 au_di(dentry
)->di_bbot
= bindex
;
222 static inline void au_set_dbwh(struct dentry
*dentry
, aufs_bindex_t bindex
)
224 DiMustWriteLock(dentry
);
225 /* dbwh can be outside of btop - bbot range */
226 au_di(dentry
)->di_bwh
= bindex
;
229 static inline void au_set_dbdiropq(struct dentry
*dentry
, aufs_bindex_t bindex
)
231 DiMustWriteLock(dentry
);
232 au_di(dentry
)->di_bdiropq
= bindex
;
235 /* ---------------------------------------------------------------------- */
237 #ifdef CONFIG_AUFS_HNOTIFY
238 static inline void au_digen_dec(struct dentry
*d
)
240 atomic_dec(&au_di(d
)->di_generation
);
243 static inline void au_hn_di_reinit(struct dentry
*dentry
)
245 dentry
->d_fsdata
= NULL
;
248 AuStubVoid(au_hn_di_reinit
, struct dentry
*dentry __maybe_unused
)
249 #endif /* CONFIG_AUFS_HNOTIFY */
251 #endif /* __KERNEL__ */
252 #endif /* __AUFS_DENTRY_H__ */