2 * Copyright (C) 2005-2011 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, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * lookup and dentry operations
23 #ifndef __AUFS_DENTRY_H__
24 #define __AUFS_DENTRY_H__
28 #include <linux/dcache.h>
29 #include <linux/aufs_type.h>
33 struct dentry
*hd_dentry
;
38 atomic_t di_generation
;
40 struct au_rwsem di_rwsem
;
41 aufs_bindex_t di_bstart
, di_bend
, di_bwh
, di_bdiropq
;
42 struct au_hdentry
*di_hdentry
;
43 } ____cacheline_aligned_in_smp
;
45 /* ---------------------------------------------------------------------- */
48 extern const struct dentry_operations aufs_dop
;
50 struct dentry
*au_lkup_one(struct qstr
*name
, struct dentry
*h_parent
,
51 struct au_branch
*br
, struct nameidata
*nd
);
52 struct dentry
*au_sio_lkup_one(struct qstr
*name
, struct dentry
*parent
,
53 struct au_branch
*br
);
54 int au_h_verify(struct dentry
*h_dentry
, unsigned int udba
, struct inode
*h_dir
,
55 struct dentry
*h_parent
, struct au_branch
*br
);
57 int au_lkup_dentry(struct dentry
*dentry
, aufs_bindex_t bstart
, mode_t type
,
58 struct nameidata
*nd
);
59 int au_lkup_neg(struct dentry
*dentry
, aufs_bindex_t bindex
);
60 int au_refresh_dentry(struct dentry
*dentry
, struct dentry
*parent
);
61 int au_reval_dpath(struct dentry
*dentry
, unsigned int sigen
);
64 void au_di_init_once(void *_di
);
65 struct au_dinfo
*au_di_alloc(struct super_block
*sb
, unsigned int lsc
);
66 void au_di_free(struct au_dinfo
*dinfo
);
67 void au_di_swap(struct au_dinfo
*a
, struct au_dinfo
*b
);
68 void au_di_cp(struct au_dinfo
*dst
, struct au_dinfo
*src
);
69 int au_di_init(struct dentry
*dentry
);
70 void au_di_fin(struct dentry
*dentry
);
71 int au_di_realloc(struct au_dinfo
*dinfo
, int nbr
);
73 void di_read_lock(struct dentry
*d
, int flags
, unsigned int lsc
);
74 void di_read_unlock(struct dentry
*d
, int flags
);
75 void di_downgrade_lock(struct dentry
*d
, int flags
);
76 void di_write_lock(struct dentry
*d
, unsigned int lsc
);
77 void di_write_unlock(struct dentry
*d
);
78 void di_write_lock2_child(struct dentry
*d1
, struct dentry
*d2
, int isdir
);
79 void di_write_lock2_parent(struct dentry
*d1
, struct dentry
*d2
, int isdir
);
80 void di_write_unlock2(struct dentry
*d1
, struct dentry
*d2
);
82 struct dentry
*au_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
);
83 struct dentry
*au_h_d_alias(struct dentry
*dentry
, aufs_bindex_t bindex
);
84 aufs_bindex_t
au_dbtail(struct dentry
*dentry
);
85 aufs_bindex_t
au_dbtaildir(struct dentry
*dentry
);
87 void au_set_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
,
88 struct dentry
*h_dentry
);
89 int au_digen_test(struct dentry
*dentry
, unsigned int sigen
);
90 int au_dbrange_test(struct dentry
*dentry
);
91 void au_update_digen(struct dentry
*dentry
);
92 void au_update_dbrange(struct dentry
*dentry
, int do_put_zero
);
93 void au_update_dbstart(struct dentry
*dentry
);
94 void au_update_dbend(struct dentry
*dentry
);
95 int au_find_dbindex(struct dentry
*dentry
, struct dentry
*h_dentry
);
97 /* ---------------------------------------------------------------------- */
99 static inline struct au_dinfo
*au_di(struct dentry
*dentry
)
101 return dentry
->d_fsdata
;
104 /* ---------------------------------------------------------------------- */
106 /* lock subclass for dinfo */
108 AuLsc_DI_CHILD
, /* child first */
109 AuLsc_DI_CHILD2
, /* rename(2), link(2), and cpup at hnotify */
110 AuLsc_DI_CHILD3
, /* copyup dirs */
114 AuLsc_DI_TMP
/* temp for replacing dinfo */
118 * di_read_lock_child, di_write_lock_child,
119 * di_read_lock_child2, di_write_lock_child2,
120 * di_read_lock_child3, di_write_lock_child3,
121 * di_read_lock_parent, di_write_lock_parent,
122 * di_read_lock_parent2, di_write_lock_parent2,
123 * di_read_lock_parent3, di_write_lock_parent3,
125 #define AuReadLockFunc(name, lsc) \
126 static inline void di_read_lock_##name(struct dentry *d, int flags) \
127 { di_read_lock(d, flags, AuLsc_DI_##lsc); }
129 #define AuWriteLockFunc(name, lsc) \
130 static inline void di_write_lock_##name(struct dentry *d) \
131 { di_write_lock(d, AuLsc_DI_##lsc); }
133 #define AuRWLockFuncs(name, lsc) \
134 AuReadLockFunc(name, lsc) \
135 AuWriteLockFunc(name, lsc)
137 AuRWLockFuncs(child
, CHILD
);
138 AuRWLockFuncs(child2
, CHILD2
);
139 AuRWLockFuncs(child3
, CHILD3
);
140 AuRWLockFuncs(parent
, PARENT
);
141 AuRWLockFuncs(parent2
, PARENT2
);
142 AuRWLockFuncs(parent3
, PARENT3
);
144 #undef AuReadLockFunc
145 #undef AuWriteLockFunc
148 #define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
149 #define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
150 #define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
152 /* ---------------------------------------------------------------------- */
154 /* todo: memory barrier? */
155 static inline unsigned int au_digen(struct dentry
*d
)
157 return atomic_read(&au_di(d
)->di_generation
);
160 static inline void au_h_dentry_init(struct au_hdentry
*hdentry
)
162 hdentry
->hd_dentry
= NULL
;
165 static inline void au_hdput(struct au_hdentry
*hd
)
171 static inline aufs_bindex_t
au_dbstart(struct dentry
*dentry
)
173 DiMustAnyLock(dentry
);
174 return au_di(dentry
)->di_bstart
;
177 static inline aufs_bindex_t
au_dbend(struct dentry
*dentry
)
179 DiMustAnyLock(dentry
);
180 return au_di(dentry
)->di_bend
;
183 static inline aufs_bindex_t
au_dbwh(struct dentry
*dentry
)
185 DiMustAnyLock(dentry
);
186 return au_di(dentry
)->di_bwh
;
189 static inline aufs_bindex_t
au_dbdiropq(struct dentry
*dentry
)
191 DiMustAnyLock(dentry
);
192 return au_di(dentry
)->di_bdiropq
;
195 /* todo: hard/soft set? */
196 static inline void au_set_dbstart(struct dentry
*dentry
, aufs_bindex_t bindex
)
198 DiMustWriteLock(dentry
);
199 au_di(dentry
)->di_bstart
= bindex
;
202 static inline void au_set_dbend(struct dentry
*dentry
, aufs_bindex_t bindex
)
204 DiMustWriteLock(dentry
);
205 au_di(dentry
)->di_bend
= bindex
;
208 static inline void au_set_dbwh(struct dentry
*dentry
, aufs_bindex_t bindex
)
210 DiMustWriteLock(dentry
);
211 /* dbwh can be outside of bstart - bend range */
212 au_di(dentry
)->di_bwh
= bindex
;
215 static inline void au_set_dbdiropq(struct dentry
*dentry
, aufs_bindex_t bindex
)
217 DiMustWriteLock(dentry
);
218 au_di(dentry
)->di_bdiropq
= bindex
;
221 /* ---------------------------------------------------------------------- */
223 #ifdef CONFIG_AUFS_HNOTIFY
224 static inline void au_digen_dec(struct dentry
*d
)
226 atomic_dec(&au_di(d
)->di_generation
);
229 static inline void au_hn_di_reinit(struct dentry
*dentry
)
231 dentry
->d_fsdata
= NULL
;
234 AuStubVoid(au_hn_di_reinit
, struct dentry
*dentry __maybe_unused
)
235 #endif /* CONFIG_AUFS_HNOTIFY */
237 #endif /* __KERNEL__ */
238 #endif /* __AUFS_DENTRY_H__ */