Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / aufs / dentry.h
1 /*
2  * Copyright (C) 2005-2013 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, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 /*
20  * lookup and dentry operations
21  */
22
23 #ifndef __AUFS_DENTRY_H__
24 #define __AUFS_DENTRY_H__
25
26 #ifdef __KERNEL__
27
28 #include <linux/dcache.h>
29 #include "rwsem.h"
30
31 struct au_hdentry {
32         struct dentry           *hd_dentry;
33         aufs_bindex_t           hd_id;
34 };
35
36 struct au_dinfo {
37         atomic_t                di_generation;
38
39         struct au_rwsem         di_rwsem;
40         aufs_bindex_t           di_bstart, di_bend, di_bwh, di_bdiropq;
41         struct au_hdentry       *di_hdentry;
42 } ____cacheline_aligned_in_smp;
43
44 /* ---------------------------------------------------------------------- */
45
46 /* dentry.c */
47 extern const struct dentry_operations aufs_dop;
48 struct au_branch;
49 struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
50                            struct au_branch *br, struct nameidata *nd);
51 struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
52                                struct au_branch *br);
53 int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
54                 struct dentry *h_parent, struct au_branch *br);
55
56 int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
57                    struct nameidata *nd);
58 int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
59 int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
60 int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
61
62 /* dinfo.c */
63 void au_di_init_once(void *_di);
64 struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
65 void au_di_free(struct au_dinfo *dinfo);
66 void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
67 void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
68 int au_di_init(struct dentry *dentry);
69 void au_di_fin(struct dentry *dentry);
70 int au_di_realloc(struct au_dinfo *dinfo, int nbr);
71
72 void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
73 void di_read_unlock(struct dentry *d, int flags);
74 void di_downgrade_lock(struct dentry *d, int flags);
75 void di_write_lock(struct dentry *d, unsigned int lsc);
76 void di_write_unlock(struct dentry *d);
77 void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
78 void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
79 void di_write_unlock2(struct dentry *d1, struct dentry *d2);
80
81 struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
82 struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
83 aufs_bindex_t au_dbtail(struct dentry *dentry);
84 aufs_bindex_t au_dbtaildir(struct dentry *dentry);
85
86 void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
87                    struct dentry *h_dentry);
88 int au_digen_test(struct dentry *dentry, unsigned int sigen);
89 int au_dbrange_test(struct dentry *dentry);
90 void au_update_digen(struct dentry *dentry);
91 void au_update_dbrange(struct dentry *dentry, int do_put_zero);
92 void au_update_dbstart(struct dentry *dentry);
93 void au_update_dbend(struct dentry *dentry);
94 int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
95
96 /* ---------------------------------------------------------------------- */
97
98 static inline struct au_dinfo *au_di(struct dentry *dentry)
99 {
100         return dentry->d_fsdata;
101 }
102
103 /* ---------------------------------------------------------------------- */
104
105 /* lock subclass for dinfo */
106 enum {
107         AuLsc_DI_CHILD,         /* child first */
108         AuLsc_DI_CHILD2,        /* rename(2), link(2), and cpup at hnotify */
109         AuLsc_DI_CHILD3,        /* copyup dirs */
110         AuLsc_DI_PARENT,
111         AuLsc_DI_PARENT2,
112         AuLsc_DI_PARENT3,
113         AuLsc_DI_TMP            /* temp for replacing dinfo */
114 };
115
116 /*
117  * di_read_lock_child, di_write_lock_child,
118  * di_read_lock_child2, di_write_lock_child2,
119  * di_read_lock_child3, di_write_lock_child3,
120  * di_read_lock_parent, di_write_lock_parent,
121  * di_read_lock_parent2, di_write_lock_parent2,
122  * di_read_lock_parent3, di_write_lock_parent3,
123  */
124 #define AuReadLockFunc(name, lsc) \
125 static inline void di_read_lock_##name(struct dentry *d, int flags) \
126 { di_read_lock(d, flags, AuLsc_DI_##lsc); }
127
128 #define AuWriteLockFunc(name, lsc) \
129 static inline void di_write_lock_##name(struct dentry *d) \
130 { di_write_lock(d, AuLsc_DI_##lsc); }
131
132 #define AuRWLockFuncs(name, lsc) \
133         AuReadLockFunc(name, lsc) \
134         AuWriteLockFunc(name, lsc)
135
136 AuRWLockFuncs(child, CHILD);
137 AuRWLockFuncs(child2, CHILD2);
138 AuRWLockFuncs(child3, CHILD3);
139 AuRWLockFuncs(parent, PARENT);
140 AuRWLockFuncs(parent2, PARENT2);
141 AuRWLockFuncs(parent3, PARENT3);
142
143 #undef AuReadLockFunc
144 #undef AuWriteLockFunc
145 #undef AuRWLockFuncs
146
147 #define DiMustNoWaiters(d)      AuRwMustNoWaiters(&au_di(d)->di_rwsem)
148 #define DiMustAnyLock(d)        AuRwMustAnyLock(&au_di(d)->di_rwsem)
149 #define DiMustWriteLock(d)      AuRwMustWriteLock(&au_di(d)->di_rwsem)
150
151 /* ---------------------------------------------------------------------- */
152
153 /* todo: memory barrier? */
154 static inline unsigned int au_digen(struct dentry *d)
155 {
156         return atomic_read(&au_di(d)->di_generation);
157 }
158
159 static inline void au_h_dentry_init(struct au_hdentry *hdentry)
160 {
161         hdentry->hd_dentry = NULL;
162 }
163
164 static inline void au_hdput(struct au_hdentry *hd)
165 {
166         if (hd)
167                 dput(hd->hd_dentry);
168 }
169
170 static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
171 {
172         DiMustAnyLock(dentry);
173         return au_di(dentry)->di_bstart;
174 }
175
176 static inline aufs_bindex_t au_dbend(struct dentry *dentry)
177 {
178         DiMustAnyLock(dentry);
179         return au_di(dentry)->di_bend;
180 }
181
182 static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
183 {
184         DiMustAnyLock(dentry);
185         return au_di(dentry)->di_bwh;
186 }
187
188 static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
189 {
190         DiMustAnyLock(dentry);
191         return au_di(dentry)->di_bdiropq;
192 }
193
194 /* todo: hard/soft set? */
195 static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
196 {
197         DiMustWriteLock(dentry);
198         au_di(dentry)->di_bstart = bindex;
199 }
200
201 static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
202 {
203         DiMustWriteLock(dentry);
204         au_di(dentry)->di_bend = bindex;
205 }
206
207 static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
208 {
209         DiMustWriteLock(dentry);
210         /* dbwh can be outside of bstart - bend range */
211         au_di(dentry)->di_bwh = bindex;
212 }
213
214 static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
215 {
216         DiMustWriteLock(dentry);
217         au_di(dentry)->di_bdiropq = bindex;
218 }
219
220 /* ---------------------------------------------------------------------- */
221
222 #ifdef CONFIG_AUFS_HNOTIFY
223 static inline void au_digen_dec(struct dentry *d)
224 {
225         atomic_dec(&au_di(d)->di_generation);
226 }
227
228 static inline void au_hn_di_reinit(struct dentry *dentry)
229 {
230         dentry->d_fsdata = NULL;
231 }
232 #else
233 AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
234 #endif /* CONFIG_AUFS_HNOTIFY */
235
236 #endif /* __KERNEL__ */
237 #endif /* __AUFS_DENTRY_H__ */