~ubuntu-branches/ubuntu/raring/aufs/raring

« back to all changes in this revision

Viewing changes to fs/aufs25/dentry.h

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2008-05-06 18:35:50 UTC
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: james.westby@ubuntu.com-20080506183550-7y7mrzkzkh2tjlfu
Tags: upstream-0+20080506
ImportĀ upstreamĀ versionĀ 0+20080506

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005-2008 Junjiro 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
 * $Id: dentry.h,v 1.4 2008/05/04 23:54:53 sfjro Exp $
 
23
 */
 
24
 
 
25
#ifndef __AUFS_DENTRY_H__
 
26
#define __AUFS_DENTRY_H__
 
27
 
 
28
#ifdef __KERNEL__
 
29
 
 
30
#include <linux/fs.h>
 
31
#include <linux/namei.h>
 
32
#include <linux/aufs_type.h>
 
33
#include "misc.h"
 
34
#include "super.h"
 
35
#include "vfsub.h"
 
36
 
 
37
/* nameidata open_intent */
 
38
enum {
 
39
        AuIntent_AUFS,
 
40
        AuIntent_BRANCH,
 
41
        AuIntent_Last
 
42
};
 
43
 
 
44
struct au_hdintent {
 
45
        struct list_head        hdi_list;
 
46
        struct file             *hdi_file[AuIntent_Last];
 
47
};
 
48
 
 
49
struct au_hdentry {
 
50
        struct dentry           *hd_dentry;
 
51
 
 
52
#ifdef CONFIG_AUFS_BR_NFS
 
53
        spinlock_t              hd_lock; /* intest_list */
 
54
        struct list_head        *hd_intent_list;
 
55
#endif
 
56
};
 
57
 
 
58
struct au_dinfo {
 
59
        atomic_t                di_generation;
 
60
 
 
61
        struct au_rwsem         di_rwsem;
 
62
        aufs_bindex_t           di_bstart, di_bend, di_bwh, di_bdiropq;
 
63
        struct au_hdentry       *di_hdentry;
 
64
};
 
65
 
 
66
/* nameidata extension flags */
 
67
#define AuNdx_DLGT      1
 
68
#define AuNdx_DIRPERM1  (1 << 1)
 
69
#define au_ftest_ndx(flags, name)       ((flags) & AuNdx_##name)
 
70
#define au_fset_ndx(flags, name)        { (flags) |= AuNdx_##name; }
 
71
#define au_fclr_ndx(flags, name)        { (flags) &= ~AuNdx_##name; }
 
72
#ifndef CONFIG_AUFS_DLGT
 
73
#undef AuNdx_DLGT
 
74
#define AuNdx_DLGT      0
 
75
#undef AuNdx_DIRPERM1
 
76
#define AuNdx_DIRPERM1  0
 
77
#endif
 
78
 
 
79
struct au_ndx {
 
80
        struct vfsmount *nfsmnt;
 
81
        unsigned int flags;
 
82
        struct nameidata *nd;
 
83
        struct au_branch *br;
 
84
        struct file *nd_file;
 
85
};
 
86
 
 
87
/* ---------------------------------------------------------------------- */
 
88
 
 
89
static inline void au_do_h_dentry_init(struct au_hdentry *hdentry)
 
90
{
 
91
        hdentry->hd_dentry = NULL;
 
92
}
 
93
 
 
94
#ifdef CONFIG_AUFS_BR_NFS
 
95
static inline void au_h_dentry_init(struct au_hdentry *hdentry)
 
96
{
 
97
        au_do_h_dentry_init(hdentry);
 
98
        spin_lock_init(&hdentry->hd_lock);
 
99
}
 
100
 
 
101
static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n)
 
102
{
 
103
        while (n--)
 
104
                spin_lock_init(&hdentry[n].hd_lock);
 
105
}
 
106
 
 
107
/* br_nfs.c */
 
108
struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
 
109
                         struct file *file);
 
110
int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
 
111
                       aufs_bindex_t bindex, struct nameidata *nd);
 
112
void au_hintent_put(struct au_hdentry *hd, int do_free);
 
113
int au_fake_intent(struct nameidata *nd, int perm);
 
114
int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
 
115
                       aufs_bindex_t bindex, struct file *file);
 
116
struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len,
 
117
                            struct au_ndx *ndx);
 
118
#else
 
119
 
 
120
static inline void au_h_dentry_init(struct au_hdentry *hdentry)
 
121
{
 
122
        au_do_h_dentry_init(hdentry);
 
123
}
 
124
 
 
125
static inline void au_h_dentry_init_all(struct au_hdentry *hdentry, int n)
 
126
{
 
127
        /* nothing */
 
128
}
 
129
 
 
130
static inline
 
131
struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
 
132
                         struct file *file)
 
133
{
 
134
        //return ERR_PTR(-ENOSYS);
 
135
        return NULL;
 
136
}
 
137
 
 
138
static inline
 
139
int au_br_nfs_h_intent(struct file *nd_file, struct dentry *dentry,
 
140
                       aufs_bindex_t bindex, struct nameidata *nd)
 
141
{
 
142
        return 0;
 
143
}
 
144
 
 
145
static inline void au_hintent_put(struct au_hdentry *hd, int do_free)
 
146
{
 
147
        /* empty */
 
148
}
 
149
 
 
150
static inline int au_fake_intent(struct nameidata *nd, int perm)
 
151
{
 
152
        return 0;
 
153
}
 
154
 
 
155
static inline
 
156
int au_hin_after_reval(struct nameidata *nd, struct dentry *dentry,
 
157
                       aufs_bindex_t bindex, struct file *file)
 
158
{
 
159
        return 0;
 
160
}
 
161
 
 
162
#ifdef CONFIG_AUFS_DLGT
 
163
static inline
 
164
struct dentry *au_lkup_hash(const char *name, struct dentry *parent, int len,
 
165
                            struct au_ndx *ndx)
 
166
{
 
167
        //return ERR_PTR(-ENOSYS);
 
168
        return vfsub_lookup_one_len(name, parent, len);
 
169
}
 
170
#endif
 
171
#endif /* CONFIG_AUFS_BR_NFS */
 
172
 
 
173
#ifdef CONFIG_AUFS_DLGT
 
174
/* dlgt.c */
 
175
struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
 
176
                                int len, unsigned int flags);
 
177
#elif defined(CONFIG_AUFS_BR_NFS)
 
178
/* regardelss kernel version */
 
179
static inline
 
180
struct dentry *au_lkup_one_dlgt(const char *name, struct dentry *parent,
 
181
                                int len, unsigned int flags)
 
182
{
 
183
        return vfsub_lookup_one_len(name, parent, len);
 
184
}
 
185
#endif
 
186
 
 
187
/* dentry.c */
 
188
extern struct dentry_operations aufs_dop;
 
189
#if defined(CONFIG_AUFS_BR_NFS) || defined(CONFIG_AUFS_DLGT)
 
190
struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
 
191
                           struct au_ndx *ndx);
 
192
#else
 
193
static inline
 
194
struct dentry *au_lkup_one(const char *name, struct dentry *parent, int len,
 
195
                           struct au_ndx *ndx)
 
196
{
 
197
        //todo: ndx->nd_file = NULL;
 
198
        return vfsub_lookup_one_len(name, parent, len);
 
199
}
 
200
#endif
 
201
struct dentry *au_sio_lkup_one(const char *name, struct dentry *parent, int len,
 
202
                               struct au_ndx *ndx);
 
203
int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
 
204
                   struct nameidata *nd);
 
205
int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
 
206
int au_refresh_hdentry(struct dentry *dentry, mode_t type);
 
207
int au_reval_dpath(struct dentry *dentry, au_gen_t sgen);
 
208
 
 
209
/* dinfo.c */
 
210
int au_alloc_dinfo(struct dentry *dentry);
 
211
struct au_dinfo *au_di(struct dentry *dentry);
 
212
 
 
213
void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
 
214
void di_read_unlock(struct dentry *d, int flags);
 
215
void di_downgrade_lock(struct dentry *d, int flags);
 
216
void di_write_lock(struct dentry *d, unsigned int lsc);
 
217
void di_write_unlock(struct dentry *d);
 
218
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
 
219
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
 
220
void di_write_unlock2(struct dentry *d1, struct dentry *d2);
 
221
 
 
222
struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
 
223
 
 
224
aufs_bindex_t au_dbtail(struct dentry *dentry);
 
225
aufs_bindex_t au_dbtaildir(struct dentry *dentry);
 
226
#if 0 // rfu
 
227
aufs_bindex_t au_dbtail_generic(struct dentry *dentry);
 
228
#endif
 
229
 
 
230
void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex);
 
231
void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
 
232
                   struct dentry *h_dentry);
 
233
 
 
234
void au_update_dbrange(struct dentry *dentry, int do_put_zero);
 
235
void au_update_dbstart(struct dentry *dentry);
 
236
void au_update_dbend(struct dentry *dentry);
 
237
int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
 
238
 
 
239
/* ---------------------------------------------------------------------- */
 
240
 
 
241
//todo: memory barrier?
 
242
static inline au_gen_t au_digen(struct dentry *d)
 
243
{
 
244
        return atomic_read(&au_di(d)->di_generation);
 
245
}
 
246
 
 
247
#ifdef CONFIG_AUFS_HINOTIFY
 
248
static inline au_gen_t au_digen_dec(struct dentry *d)
 
249
{
 
250
        return atomic_dec_return(&au_di(d)->di_generation);
 
251
}
 
252
#endif /* CONFIG_AUFS_HINOTIFY */
 
253
 
 
254
/* ---------------------------------------------------------------------- */
 
255
 
 
256
/* lock subclass for dinfo */
 
257
enum {
 
258
        AuLsc_DI_CHILD,         /* child first */
 
259
        AuLsc_DI_CHILD2,        /* rename(2), link(2), and cpup at hinotify */
 
260
        AuLsc_DI_CHILD3,        /* copyup dirs */
 
261
        AuLsc_DI_PARENT,
 
262
        AuLsc_DI_PARENT2,
 
263
        AuLsc_DI_PARENT3
 
264
};
 
265
 
 
266
/*
 
267
 * di_read_lock_child, di_write_lock_child,
 
268
 * di_read_lock_child2, di_write_lock_child2,
 
269
 * di_read_lock_child3, di_write_lock_child3,
 
270
 * di_read_lock_parent, di_write_lock_parent,
 
271
 * di_read_lock_parent2, di_write_lock_parent2,
 
272
 * di_read_lock_parent3, di_write_lock_parent3,
 
273
 */
 
274
#define AuReadLockFunc(name, lsc) \
 
275
static inline void di_read_lock_##name(struct dentry *d, int flags) \
 
276
{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
 
277
 
 
278
#define AuWriteLockFunc(name, lsc) \
 
279
static inline void di_write_lock_##name(struct dentry *d) \
 
280
{ di_write_lock(d, AuLsc_DI_##lsc); }
 
281
 
 
282
#define AuRWLockFuncs(name, lsc) \
 
283
        AuReadLockFunc(name, lsc) \
 
284
        AuWriteLockFunc(name, lsc)
 
285
 
 
286
AuRWLockFuncs(child, CHILD);
 
287
AuRWLockFuncs(child2, CHILD2);
 
288
AuRWLockFuncs(child3, CHILD3);
 
289
AuRWLockFuncs(parent, PARENT);
 
290
AuRWLockFuncs(parent2, PARENT2);
 
291
AuRWLockFuncs(parent3, PARENT3);
 
292
 
 
293
#undef AuReadLockFunc
 
294
#undef AuWriteLockFunc
 
295
#undef AuRWLockFuncs
 
296
 
 
297
/* to debug easier, do not make them inlined functions */
 
298
#define DiMustReadLock(d) do { \
 
299
        SiMustAnyLock((d)->d_sb); \
 
300
        AuRwMustReadLock(&au_di(d)->di_rwsem); \
 
301
} while (0)
 
302
 
 
303
#define DiMustWriteLock(d) do { \
 
304
        SiMustAnyLock((d)->d_sb); \
 
305
        AuRwMustWriteLock(&au_di(d)->di_rwsem); \
 
306
} while (0)
 
307
 
 
308
#define DiMustAnyLock(d) do { \
 
309
        SiMustAnyLock((d)->d_sb); \
 
310
        AuRwMustAnyLock(&au_di(d)->di_rwsem); \
 
311
} while (0)
 
312
 
 
313
#define DiMustNoWaiters(d)      AuRwMustNoWaiters(&au_di(d)->di_rwsem)
 
314
 
 
315
/* ---------------------------------------------------------------------- */
 
316
 
 
317
static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
 
318
{
 
319
        DiMustAnyLock(dentry);
 
320
        return au_di(dentry)->di_bstart;
 
321
}
 
322
 
 
323
static inline aufs_bindex_t au_dbend(struct dentry *dentry)
 
324
{
 
325
        DiMustAnyLock(dentry);
 
326
        return au_di(dentry)->di_bend;
 
327
}
 
328
 
 
329
static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
 
330
{
 
331
        DiMustAnyLock(dentry);
 
332
        return au_di(dentry)->di_bwh;
 
333
}
 
334
 
 
335
static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
 
336
{
 
337
        DiMustAnyLock(dentry);
 
338
        AuDebugOn(dentry->d_inode
 
339
                  && dentry->d_inode->i_mode
 
340
                  && !S_ISDIR(dentry->d_inode->i_mode));
 
341
        return au_di(dentry)->di_bdiropq;
 
342
}
 
343
 
 
344
// hard/soft set
 
345
static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
 
346
{
 
347
        DiMustWriteLock(dentry);
 
348
        AuDebugOn(au_sbend(dentry->d_sb) < bindex);
 
349
        /* */
 
350
        au_di(dentry)->di_bstart = bindex;
 
351
}
 
352
 
 
353
static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
 
354
{
 
355
        DiMustWriteLock(dentry);
 
356
        AuDebugOn(au_sbend(dentry->d_sb) < bindex
 
357
                  || bindex < au_dbstart(dentry));
 
358
        au_di(dentry)->di_bend = bindex;
 
359
}
 
360
 
 
361
static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
 
362
{
 
363
        DiMustWriteLock(dentry);
 
364
        AuDebugOn(au_sbend(dentry->d_sb) < bindex);
 
365
        /* dbwh can be outside of bstart - bend range */
 
366
        au_di(dentry)->di_bwh = bindex;
 
367
}
 
368
 
 
369
static inline void au_hdput(struct au_hdentry *hd, int do_free)
 
370
{
 
371
        au_hintent_put(hd, do_free);
 
372
        dput(hd->hd_dentry);
 
373
}
 
374
 
 
375
static inline void au_update_digen(struct dentry *dentry)
 
376
{
 
377
        //DiMustWriteLock(dentry);
 
378
        AuDebugOn(!dentry->d_sb);
 
379
        atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
 
380
        //smp_mb(); /* atomic_set */
 
381
}
 
382
 
 
383
#endif /* __KERNEL__ */
 
384
#endif /* __AUFS_DENTRY_H__ */