~ubuntu-branches/ubuntu/precise/aufs/precise

« back to all changes in this revision

Viewing changes to fs/aufs/dentry.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2007-05-09 15:29:28 UTC
  • Revision ID: james.westby@ubuntu.com-20070509152928-4sywrmkifvz0bq02
Tags: upstream-0+20070509
ImportĀ upstreamĀ versionĀ 0+20070509

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005, 2006, 2007 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
/* $Id: dentry.c,v 1.40 2007/05/07 03:43:36 sfjro Exp $ */
 
20
 
 
21
//#include <linux/fs.h>
 
22
//#include <linux/namei.h>
 
23
#include "aufs.h"
 
24
 
 
25
#ifdef CONFIG_AUFS_LHASH_PATCH
 
26
 
 
27
#ifdef CONFIG_AUFS_DLGT
 
28
struct lookup_hash_args {
 
29
        struct dentry **errp;
 
30
        struct qstr *name;
 
31
        struct dentry *base;
 
32
        struct nameidata *nd;
 
33
};
 
34
 
 
35
static void call_lookup_hash(void *args)
 
36
{
 
37
        struct lookup_hash_args *a = args;
 
38
        *a->errp = __lookup_hash(a->name, a->base, a->nd);
 
39
}
 
40
#endif /* CONFIG_AUFS_DLGT */
 
41
 
 
42
static struct dentry *lkup_hash(const char *name, struct dentry *parent,
 
43
                                int len, struct lkup_args *lkup)
 
44
{
 
45
        struct dentry *dentry;
 
46
        char *p;
 
47
        unsigned long hash;
 
48
        struct qstr this;
 
49
        unsigned int c;
 
50
        struct nameidata tmp_nd;
 
51
 
 
52
        dentry = ERR_PTR(-EACCES);
 
53
        this.name = name;
 
54
        this.len = len;
 
55
        if (unlikely(!len))
 
56
                goto out;
 
57
 
 
58
        p = (void*)name;
 
59
        hash = init_name_hash();
 
60
        while (len--) {
 
61
                c = *p++;
 
62
                if (unlikely(c == '/' || c == '\0'))
 
63
                        goto out;
 
64
                hash = partial_name_hash(c, hash);
 
65
        }
 
66
        this.hash = end_name_hash(hash);
 
67
 
 
68
        memset(&tmp_nd, 0, sizeof(tmp_nd));
 
69
        tmp_nd.dentry = dget(parent);
 
70
        tmp_nd.mnt = mntget(lkup->nfsmnt);
 
71
#ifndef CONFIG_AUFS_DLGT
 
72
        dentry = __lookup_hash(&this, parent, &tmp_nd);
 
73
#else
 
74
        if (!lkup->dlgt)
 
75
                dentry = __lookup_hash(&this, parent, &tmp_nd);
 
76
        else {
 
77
                struct lookup_hash_args args = {
 
78
                        .errp   = &dentry,
 
79
                        .name   = &this,
 
80
                        .base   = parent,
 
81
                        .nd     = &tmp_nd
 
82
                };
 
83
                au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1);
 
84
        }
 
85
#endif
 
86
        path_release(&tmp_nd);
 
87
 
 
88
 out:
 
89
        TraceErrPtr(dentry);
 
90
        return dentry;
 
91
}
 
92
#elif defined(CONFIG_AUFS_DLGT)
 
93
static struct dentry *lkup_hash(const char *name, struct dentry *parent,
 
94
                                int len, struct lkup_args *lkup)
 
95
{
 
96
        return ERR_PTR(-ENOSYS);
 
97
}
 
98
#endif
 
99
 
 
100
#ifdef CONFIG_AUFS_DLGT
 
101
struct lookup_one_len_args {
 
102
        struct dentry **errp;
 
103
        const char *name;
 
104
        struct dentry *parent;
 
105
        int len;
 
106
};
 
107
 
 
108
static void call_lookup_one_len(void *args)
 
109
{
 
110
        struct lookup_one_len_args *a = args;
 
111
        *a->errp = lookup_one_len(a->name, a->parent, a->len);
 
112
}
 
113
#endif /* CONFIG_AUFS_DLGT */
 
114
 
 
115
#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
 
116
/* cf. lookup_one_len() in linux/fs/namei.c */
 
117
struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
 
118
                        struct lkup_args *lkup)
 
119
{
 
120
        struct dentry *dentry;
 
121
 
 
122
        LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n",
 
123
                  DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt);
 
124
 
 
125
        if (!lkup->nfsmnt) {
 
126
#ifndef CONFIG_AUFS_DLGT
 
127
                dentry = lookup_one_len(name, parent, len);
 
128
#else
 
129
                if (!lkup->dlgt)
 
130
                        dentry = lookup_one_len(name, parent, len);
 
131
                else {
 
132
                        struct lookup_one_len_args args = {
 
133
                                .errp   = &dentry,
 
134
                                .name   = name,
 
135
                                .parent = parent,
 
136
                                .len    = len
 
137
                        };
 
138
                        au_wkq_wait(call_lookup_one_len, &args, /*dlgt*/1);
 
139
                }
 
140
#endif
 
141
        } else
 
142
                dentry = lkup_hash(name, parent, len, lkup);
 
143
 
 
144
        TraceErrPtr(dentry);
 
145
        return dentry;
 
146
}
 
147
#endif
 
148
 
 
149
struct lkup_one_args {
 
150
        struct dentry **errp;
 
151
        const char *name;
 
152
        struct dentry *parent;
 
153
        int len;
 
154
        struct lkup_args *lkup;
 
155
};
 
156
 
 
157
static void call_lkup_one(void *args)
 
158
{
 
159
        struct lkup_one_args *a = args;
 
160
        *a->errp = lkup_one(a->name, a->parent, a->len, a->lkup);
 
161
}
 
162
 
 
163
/*
 
164
 * returns positive/negative dentry, NULL or an error.
 
165
 * NULL means whiteout-ed or not-found.
 
166
 */
 
167
static struct dentry *do_lookup(struct dentry *hidden_parent,
 
168
                                struct dentry *dentry, aufs_bindex_t bindex,
 
169
                                struct qstr *wh_name, int allow_neg,
 
170
                                mode_t type, int dlgt)
 
171
{
 
172
        struct dentry *hidden_dentry;
 
173
        int wh_found, wh_able, opq;
 
174
        struct inode *hidden_dir, *hidden_inode;
 
175
        struct qstr *name;
 
176
        struct super_block *sb;
 
177
        struct lkup_args lkup = {.dlgt = dlgt};
 
178
 
 
179
        LKTRTrace("%.*s/%.*s, b%d, allow_neg %d, type 0%o, dlgt %d\n",
 
180
                  DLNPair(hidden_parent), DLNPair(dentry), bindex, allow_neg,
 
181
                  type, dlgt);
 
182
        DEBUG_ON(IS_ROOT(dentry));
 
183
        hidden_dir = hidden_parent->d_inode;
 
184
        IMustLock(hidden_dir);
 
185
 
 
186
        wh_found = 0;
 
187
        sb = dentry->d_sb;
 
188
        wh_able = sbr_is_whable(sb, bindex);
 
189
        lkup.nfsmnt = au_nfsmnt(sb, bindex);
 
190
        name = &dentry->d_name;
 
191
        if (unlikely(wh_able)) {
 
192
#if 0 //def CONFIG_AUFS_AS_BRANCH
 
193
                if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_LEN))
 
194
                        wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0,
 
195
                                         &lkup);
 
196
                else
 
197
                        wh_found = -EPERM;
 
198
#else
 
199
                wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0, &lkup);
 
200
#endif
 
201
        }
 
202
        //if (LktrCond) wh_found = -1;
 
203
        hidden_dentry = ERR_PTR(wh_found);
 
204
        if (!wh_found)
 
205
                goto real_lookup;
 
206
        if (unlikely(wh_found < 0))
 
207
                goto out;
 
208
 
 
209
        /* We found a whiteout */
 
210
        //set_dbend(dentry, bindex);
 
211
        set_dbwh(dentry, bindex);
 
212
        if (!allow_neg)
 
213
                return NULL; /* success */
 
214
 
 
215
 real_lookup:
 
216
        // do not superio.
 
217
        hidden_dentry = lkup_one(name->name, hidden_parent, name->len, &lkup);
 
218
        //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
 
219
        if (IS_ERR(hidden_dentry))
 
220
                goto out;
 
221
        DEBUG_ON(d_unhashed(hidden_dentry));
 
222
        hidden_inode = hidden_dentry->d_inode;
 
223
        if (!hidden_inode) {
 
224
                if (!allow_neg)
 
225
                        goto out_neg;
 
226
        } else if (wh_found
 
227
                   || (type && type != (hidden_inode->i_mode & S_IFMT)))
 
228
                goto out_neg;
 
229
 
 
230
        if (dbend(dentry) <= bindex)
 
231
                set_dbend(dentry, bindex);
 
232
        if (dbstart(dentry) == -1 || bindex < dbstart(dentry))
 
233
                set_dbstart(dentry, bindex);
 
234
        set_h_dptr(dentry, bindex, hidden_dentry);
 
235
 
 
236
        if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode) || !wh_able)
 
237
                return hidden_dentry; /* success */
 
238
 
 
239
        hi_lock_child(hidden_inode);
 
240
        opq = is_diropq(hidden_dentry, &lkup);
 
241
        //if (LktrCond) opq = -1;
 
242
        i_unlock(hidden_inode);
 
243
        if (opq > 0)
 
244
                set_dbdiropq(dentry, bindex);
 
245
        else if (unlikely(opq < 0)) {
 
246
                set_h_dptr(dentry, bindex, NULL);
 
247
                hidden_dentry = ERR_PTR(opq);
 
248
        }
 
249
        goto out;
 
250
 
 
251
 out_neg:
 
252
        dput(hidden_dentry);
 
253
        hidden_dentry = NULL;
 
254
 out:
 
255
        TraceErrPtr(hidden_dentry);
 
256
        return hidden_dentry;
 
257
}
 
258
 
 
259
/*
 
260
 * returns the number of hidden positive dentries,
 
261
 * otherwise an error.
 
262
 */
 
263
int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type)
 
264
{
 
265
        int npositive, err, allow_neg, dlgt;
 
266
        struct dentry *parent;
 
267
        aufs_bindex_t bindex, btail;
 
268
        const struct qstr *name = &dentry->d_name;
 
269
        struct qstr whname;
 
270
        struct super_block *sb;
 
271
 
 
272
        LKTRTrace("%.*s, b%d, type 0%o\n", LNPair(name), bstart, type);
 
273
        DEBUG_ON(bstart < 0 || IS_ROOT(dentry));
 
274
        parent = dget_parent(dentry);
 
275
 
 
276
#if 1 //ndef CONFIG_AUFS_AS_BRANCH
 
277
        err = -EPERM;
 
278
        if (unlikely(!strncmp(name->name, AUFS_WH_PFX, AUFS_WH_LEN)))
 
279
                goto out;
 
280
#endif
 
281
 
 
282
        err = au_alloc_whname(name->name, name->len, &whname);
 
283
        //if (LktrCond) {au_free_whname(&whname); err = -1;}
 
284
        if (unlikely(err))
 
285
                goto out;
 
286
 
 
287
        sb = dentry->d_sb;
 
288
        dlgt = need_dlgt(sb);
 
289
        allow_neg = !type;
 
290
        npositive = 0;
 
291
        btail = dbtaildir(parent);
 
292
        for (bindex = bstart; bindex <= btail; bindex++) {
 
293
                struct dentry *hidden_parent, *hidden_dentry;
 
294
                struct inode *hidden_inode;
 
295
                struct inode *hidden_dir;
 
296
 
 
297
                hidden_dentry = au_h_dptr_i(dentry, bindex);
 
298
                if (hidden_dentry) {
 
299
                        if (hidden_dentry->d_inode)
 
300
                                npositive++;
 
301
                        if (type != S_IFDIR)
 
302
                                break;
 
303
                        continue;
 
304
                }
 
305
                hidden_parent = au_h_dptr_i(parent, bindex);
 
306
                if (!hidden_parent)
 
307
                        continue;
 
308
                hidden_dir = hidden_parent->d_inode;
 
309
                if (!hidden_dir || !S_ISDIR(hidden_dir->i_mode))
 
310
                        continue;
 
311
 
 
312
                hi_lock_parent(hidden_dir);
 
313
                hidden_dentry = do_lookup(hidden_parent, dentry, bindex,
 
314
                                          &whname, allow_neg, type, dlgt);
 
315
                // do not dput for testing
 
316
                //if (LktrCond) {hidden_dentry = ERR_PTR(-1);}
 
317
                i_unlock(hidden_dir);
 
318
                err = PTR_ERR(hidden_dentry);
 
319
                if (IS_ERR(hidden_dentry))
 
320
                        goto out_wh;
 
321
                allow_neg = 0;
 
322
 
 
323
                if (dbwh(dentry) != -1)
 
324
                        break;
 
325
                if (!hidden_dentry)
 
326
                        continue;
 
327
                hidden_inode = hidden_dentry->d_inode;
 
328
                if (!hidden_inode)
 
329
                        continue;
 
330
                npositive++;
 
331
                if (!type)
 
332
                        type = hidden_inode->i_mode & S_IFMT;
 
333
                if (type != S_IFDIR)
 
334
                        break;
 
335
                else if (dbdiropq(dentry) != -1)
 
336
                        break;
 
337
        }
 
338
 
 
339
        if (npositive) {
 
340
                LKTRLabel(positive);
 
341
                au_update_dbstart(dentry);
 
342
        }
 
343
        err = npositive;
 
344
 
 
345
 out_wh:
 
346
        au_free_whname(&whname);
 
347
 out:
 
348
        dput(parent);
 
349
        TraceErr(err);
 
350
        return err;
 
351
}
 
352
 
 
353
struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
 
354
                            struct lkup_args *lkup)
 
355
{
 
356
        struct dentry *dentry;
 
357
 
 
358
        LKTRTrace("%.*s/%.*s\n", DLNPair(parent), len, name);
 
359
        IMustLock(parent->d_inode);
 
360
 
 
361
        if (!au_test_perm(parent->d_inode, MAY_EXEC, lkup->dlgt))
 
362
                dentry = lkup_one(name, parent, len, lkup);
 
363
        else {
 
364
                // ugly
 
365
                int dlgt = lkup->dlgt;
 
366
                struct lkup_one_args args = {
 
367
                        .errp   = &dentry,
 
368
                        .name   = name,
 
369
                        .parent = parent,
 
370
                        .len    = len,
 
371
                        .lkup   = lkup
 
372
                };
 
373
 
 
374
                lkup->dlgt = 0;
 
375
                au_wkq_wait(call_lkup_one, &args, /*dlgt*/0);
 
376
                lkup->dlgt = dlgt;
 
377
        }
 
378
 
 
379
        TraceErrPtr(dentry);
 
380
        return dentry;
 
381
}
 
382
 
 
383
/*
 
384
 * lookup @dentry on @bindex which should be negative.
 
385
 */
 
386
int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
 
387
{
 
388
        int err;
 
389
        struct dentry *parent, *hidden_parent, *hidden_dentry;
 
390
        struct inode *hidden_dir;
 
391
        struct lkup_args lkup;
 
392
 
 
393
        LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
 
394
        parent = dget_parent(dentry);
 
395
        DEBUG_ON(!parent || !parent->d_inode
 
396
                 || !S_ISDIR(parent->d_inode->i_mode));
 
397
        hidden_parent = au_h_dptr_i(parent, bindex);
 
398
        DEBUG_ON(!hidden_parent);
 
399
        hidden_dir = hidden_parent->d_inode;
 
400
        DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
 
401
        IMustLock(hidden_dir);
 
402
 
 
403
        lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bindex);
 
404
        lkup.dlgt = need_dlgt(dentry->d_sb);
 
405
        hidden_dentry = sio_lkup_one(dentry->d_name.name, hidden_parent,
 
406
                                     dentry->d_name.len, &lkup);
 
407
        //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
 
408
        err = PTR_ERR(hidden_dentry);
 
409
        if (IS_ERR(hidden_dentry))
 
410
                goto out;
 
411
        if (unlikely(hidden_dentry->d_inode)) {
 
412
                err = -EIO;
 
413
                IOErr("b%d %.*s should be negative.%s\n",
 
414
                      bindex, DLNPair(hidden_dentry),
 
415
                      au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY) ? "" :
 
416
                        " Try udba=inotify.");
 
417
                dput(hidden_dentry);
 
418
                goto out;
 
419
        }
 
420
 
 
421
        if (bindex < dbstart(dentry))
 
422
                set_dbstart(dentry, bindex);
 
423
        if (dbend(dentry) < bindex)
 
424
                set_dbend(dentry, bindex);
 
425
        set_h_dptr(dentry, bindex, hidden_dentry);
 
426
        err = 0;
 
427
 
 
428
 out:
 
429
        dput(parent);
 
430
        TraceErr(err);
 
431
        return err;
 
432
}
 
433
 
 
434
/*
 
435
 * returns the number of found hidden positive dentries,
 
436
 * otherwise an error.
 
437
 */
 
438
int au_refresh_hdentry(struct dentry *dentry, mode_t type)
 
439
{
 
440
        int npositive, pgen, new_sz, sgen, dgen;
 
441
        struct aufs_dinfo *dinfo;
 
442
        struct super_block *sb;
 
443
        struct dentry *parent;
 
444
        aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend;
 
445
        struct aufs_hdentry *p;
 
446
        //struct nameidata nd;
 
447
 
 
448
        LKTRTrace("%.*s, type 0%o\n", DLNPair(dentry), type);
 
449
        DiMustWriteLock(dentry);
 
450
        sb = dentry->d_sb;
 
451
        DEBUG_ON(IS_ROOT(dentry));
 
452
        parent = dget_parent(dentry);
 
453
        pgen = au_digen(parent);
 
454
        sgen = au_sigen(sb);
 
455
        dgen = au_digen(dentry);
 
456
        DEBUG_ON(pgen != sgen
 
457
                 || AufsGenOlder(sgen, dgen)
 
458
                 || AufsGenOlder(pgen, dgen));
 
459
 
 
460
        npositive = -ENOMEM;
 
461
        new_sz = sizeof(*dinfo->di_hdentry) * (sbend(sb) + 1);
 
462
        dinfo = dtodi(dentry);
 
463
        p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1),
 
464
                         new_sz, GFP_KERNEL);
 
465
        //p = NULL;
 
466
        if (unlikely(!p))
 
467
                goto out;
 
468
        dinfo->di_hdentry = p;
 
469
 
 
470
        bend = dinfo->di_bend;
 
471
        bwh = dinfo->di_bwh;
 
472
        bdiropq = dinfo->di_bdiropq;
 
473
        p += dinfo->di_bstart;
 
474
        for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
 
475
                struct dentry *hd, *hdp;
 
476
                struct aufs_hdentry tmp, *q;
 
477
                aufs_bindex_t new_bindex;
 
478
 
 
479
                hd = p->hd_dentry;
 
480
                if (!hd)
 
481
                        continue;
 
482
                hdp = dget_parent(hd);
 
483
                if (hdp == au_h_dptr_i(parent, bindex)) {
 
484
                        dput(hdp);
 
485
                        continue;
 
486
                }
 
487
 
 
488
                new_bindex = au_find_dbindex(parent, hdp);
 
489
                dput(hdp);
 
490
                DEBUG_ON(new_bindex == bindex);
 
491
                if (dinfo->di_bwh == bindex)
 
492
                        bwh = new_bindex;
 
493
                if (dinfo->di_bdiropq == bindex)
 
494
                        bdiropq = new_bindex;
 
495
                if (new_bindex < 0) { // test here
 
496
                        hdput(p);
 
497
                        p->hd_dentry = NULL;
 
498
                        continue;
 
499
                }
 
500
                /* swap two hidden dentries, and loop again */
 
501
                q = dinfo->di_hdentry + new_bindex;
 
502
                tmp = *q;
 
503
                *q = *p;
 
504
                *p = tmp;
 
505
                if (tmp.hd_dentry) {
 
506
                        bindex--;
 
507
                        p--;
 
508
                }
 
509
        }
 
510
 
 
511
        // test here
 
512
        dinfo->di_bwh = -1;
 
513
        if (unlikely(bwh != -1 && bwh <= sbend(sb) && sbr_is_whable(sb, bwh)))
 
514
                dinfo->di_bwh = bwh;
 
515
        dinfo->di_bdiropq = -1;
 
516
        if (unlikely(bdiropq != -1 && bdiropq <= sbend(sb)
 
517
                     && sbr_is_whable(sb, bdiropq)))
 
518
                dinfo->di_bdiropq = bdiropq;
 
519
        parent_bend = dbend(parent);
 
520
        p = dinfo->di_hdentry;
 
521
        for (bindex = 0; bindex <= parent_bend; bindex++, p++)
 
522
                if (p->hd_dentry) {
 
523
                        dinfo->di_bstart = bindex;
 
524
                        break;
 
525
                }
 
526
        p = dinfo->di_hdentry + parent_bend;
 
527
        //for (bindex = parent_bend; bindex > dinfo->di_bstart; bindex--, p--)
 
528
        for (bindex = parent_bend; bindex >= 0; bindex--, p--)
 
529
                if (p->hd_dentry) {
 
530
                        dinfo->di_bend = bindex;
 
531
                        break;
 
532
                }
 
533
 
 
534
        npositive = 0;
 
535
        parent_bstart = dbstart(parent);
 
536
        if (type != S_IFDIR && dinfo->di_bstart == parent_bstart)
 
537
                goto out_dgen; /* success */
 
538
 
 
539
#if 0
 
540
        nd.last_type = LAST_ROOT;
 
541
        nd.flags = LOOKUP_FOLLOW;
 
542
        nd.depth = 0;
 
543
        nd.mnt = mntget(??);
 
544
        nd.dentry = dget(parent);
 
545
#endif
 
546
        npositive = lkup_dentry(dentry, parent_bstart, type);
 
547
        //if (LktrCond) npositive = -1;
 
548
        if (npositive < 0)
 
549
                goto out;
 
550
 
 
551
 out_dgen:
 
552
        au_update_digen(dentry);
 
553
 out:
 
554
        dput(parent);
 
555
        TraceErr(npositive);
 
556
        return npositive;
 
557
}
 
558
 
 
559
static int h_d_revalidate(struct dentry *dentry, struct nameidata *nd,
 
560
                          int do_udba)
 
561
{
 
562
        int err, plus, locked, unhashed, is_root, h_plus, is_nfs;
 
563
        struct nameidata fake_nd, *p;
 
564
        aufs_bindex_t bindex, btail, bstart, ibs, ibe;
 
565
        struct super_block *sb;
 
566
        struct inode *inode, *first, *h_inode, *h_cached_inode;
 
567
        umode_t mode, h_mode;
 
568
        struct dentry *h_dentry;
 
569
        int (*reval)(struct dentry *, struct nameidata *);
 
570
        struct qstr *name;
 
571
 
 
572
        LKTRTrace("%.*s\n", DLNPair(dentry));
 
573
        inode = dentry->d_inode;
 
574
        DEBUG_ON(inode && au_digen(dentry) != au_iigen(inode));
 
575
        //DbgDentry(dentry);
 
576
        //DbgInode(inode);
 
577
 
 
578
        err = 0;
 
579
        sb = dentry->d_sb;
 
580
        plus = 0;
 
581
        mode = 0;
 
582
        first = NULL;
 
583
        ibs = ibe = -1;
 
584
        unhashed = d_unhashed(dentry);
 
585
        is_root = IS_ROOT(dentry);
 
586
        name = &dentry->d_name;
 
587
 
 
588
        /*
 
589
         * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
 
590
         * But inotify doesn't fire some necessary events,
 
591
         *      IN_ATTRIB for atime/nlink/pageio
 
592
         *      IN_DELETE for NFS dentry
 
593
         * Let's do REVAL test too.
 
594
         */
 
595
        if (do_udba && inode) {
 
596
                mode = (inode->i_mode & S_IFMT);
 
597
                plus = (inode->i_nlink > 0);
 
598
                first = au_h_iptr(inode);
 
599
                ibs = ibstart(inode);
 
600
                ibe = ibend(inode);
 
601
        }
 
602
 
 
603
        btail = bstart = dbstart(dentry);
 
604
        if (inode && S_ISDIR(inode->i_mode))
 
605
                btail = dbtaildir(dentry);
 
606
        locked = 0;
 
607
        if (nd) {
 
608
                fake_nd = *nd;
 
609
#ifndef CONFIG_AUFS_FAKE_DM
 
610
                if (dentry != nd->dentry) {
 
611
                        di_read_lock_parent(nd->dentry, 0);
 
612
                        locked = 1;
 
613
                }
 
614
#endif
 
615
        }
 
616
        for (bindex = bstart; bindex <= btail; bindex++) {
 
617
                h_dentry = au_h_dptr_i(dentry, bindex);
 
618
                if (unlikely(!h_dentry))
 
619
                        continue;
 
620
                if (unlikely(do_udba
 
621
                             && !is_root
 
622
                             && (unhashed != d_unhashed(h_dentry)
 
623
#if 1
 
624
                                 || name->len != h_dentry->d_name.len
 
625
                                 || memcmp(name->name, h_dentry->d_name.name,
 
626
                                           name->len)
 
627
#endif
 
628
                                     ))) {
 
629
                        LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n",
 
630
                                  unhashed, d_unhashed(h_dentry),
 
631
                                  DLNPair(dentry), DLNPair(h_dentry));
 
632
                        goto err;
 
633
                }
 
634
 
 
635
                reval = NULL;
 
636
                if (h_dentry->d_op)
 
637
                        reval = h_dentry->d_op->d_revalidate;
 
638
                if (unlikely(reval)) {
 
639
                        //LKTRLabel(hidden reval);
 
640
                        p = fake_dm(&fake_nd, nd, sb, bindex);
 
641
                        DEBUG_ON(IS_ERR(p));
 
642
                        err = !reval(h_dentry, p);
 
643
                        fake_dm_release(p);
 
644
                        if (unlikely(err)) {
 
645
                                //Dbg("here\n");
 
646
                                goto err;
 
647
                        }
 
648
                }
 
649
 
 
650
                if (unlikely(!do_udba))
 
651
                        continue;
 
652
 
 
653
                /* UDBA tests */
 
654
                h_inode = h_dentry->d_inode;
 
655
                if (unlikely(!!inode != !!h_inode)) {
 
656
                        //Dbg("here\n");
 
657
                        goto err;
 
658
                }
 
659
 
 
660
                h_plus = plus;
 
661
                h_mode = mode;
 
662
                h_cached_inode = h_inode;
 
663
                is_nfs = 0;
 
664
                if (h_inode) {
 
665
                        h_mode = (h_inode->i_mode & S_IFMT);
 
666
                        h_plus = (h_inode->i_nlink > 0);
 
667
                }
 
668
                if (inode && ibs <= bindex && bindex <= ibe) {
 
669
                        h_cached_inode = au_h_iptr_i(inode, bindex);
 
670
                        //is_nfs = au_is_nfs(h_cached_inode->i_sb);
 
671
                }
 
672
 
 
673
                LKTRTrace("{%d, 0%o, %p}, h{%d, 0%o, %p}\n",
 
674
                          plus, mode, h_cached_inode,
 
675
                          h_plus, h_mode, h_inode);
 
676
                if (unlikely(plus != h_plus || mode != h_mode
 
677
                             || (h_cached_inode != h_inode /* && !is_nfs */))) {
 
678
                        //Dbg("here\n");
 
679
                        goto err;
 
680
                }
 
681
                continue;
 
682
 
 
683
        err:
 
684
                err = -EINVAL;
 
685
                break;
 
686
        }
 
687
#ifndef CONFIG_AUFS_FAKE_DM
 
688
        if (unlikely(locked))
 
689
                di_read_unlock(nd->dentry, 0);
 
690
#endif
 
691
 
 
692
#if 0
 
693
        // some filesystem uses CURRENT_TIME_SEC instead of CURRENT_TIME.
 
694
        // NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED.
 
695
#if 0
 
696
                     && (!timespec_equal(&inode->i_ctime, &first->i_ctime)
 
697
                         || !timespec_equal(&inode->i_atime, &first->i_atime))
 
698
#endif
 
699
        if (unlikely(!err && udba && first))
 
700
                au_cpup_attr_all(inode);
 
701
#endif
 
702
 
 
703
        TraceErr(err);
 
704
        return err;
 
705
}
 
706
 
 
707
static int simple_reval_dpath(struct dentry *dentry, int sgen)
 
708
{
 
709
        int err;
 
710
        mode_t type;
 
711
        struct dentry *parent;
 
712
        struct inode *inode;
 
713
 
 
714
        LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
 
715
        SiMustAnyLock(dentry->d_sb);
 
716
        DiMustWriteLock(dentry);
 
717
        inode = dentry->d_inode;
 
718
        DEBUG_ON(!inode);
 
719
 
 
720
        if (!AufsGenOlder(au_digen(dentry), sgen))
 
721
                return 0;
 
722
 
 
723
        parent = dget_parent(dentry);
 
724
        di_read_lock_parent(parent, AUFS_I_RLOCK);
 
725
        DEBUG_ON(au_digen(parent) != sgen);
 
726
#ifdef CONFIG_AUFS_DEBUG
 
727
        {
 
728
                struct dentry *d = parent;
 
729
                while (!IS_ROOT(d)) {
 
730
                        DEBUG_ON(au_digen(d) != sgen);
 
731
                        d = d->d_parent;
 
732
                }
 
733
        }
 
734
#endif
 
735
        type = (inode->i_mode & S_IFMT);
 
736
        /* returns a number of positive dentries */
 
737
        err = au_refresh_hdentry(dentry, type);
 
738
        if (err >= 0)
 
739
                err = au_refresh_hinode(inode, dentry);
 
740
        di_read_unlock(parent, AUFS_I_RLOCK);
 
741
        dput(parent);
 
742
        TraceErr(err);
 
743
        return err;
 
744
}
 
745
 
 
746
int au_reval_dpath(struct dentry *dentry, int sgen)
 
747
{
 
748
        int err;
 
749
        struct dentry *d, *parent;
 
750
        struct inode *inode;
 
751
 
 
752
        LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
 
753
        DEBUG_ON(!dentry->d_inode);
 
754
        DiMustWriteLock(dentry);
 
755
 
 
756
        if (!stosi(dentry->d_sb)->si_failed_refresh_dirs)
 
757
                return simple_reval_dpath(dentry, sgen);
 
758
 
 
759
        /* slow loop, keep it simple and stupid */
 
760
        /* cf: cpup_dirs() */
 
761
        err = 0;
 
762
        while (au_digen(dentry) != sgen) {
 
763
                d = dentry;
 
764
                while (1) {
 
765
                        parent = d->d_parent; // dget_parent()
 
766
                        if (au_digen(parent) == sgen)
 
767
                                break;
 
768
                        d = parent;
 
769
                }
 
770
 
 
771
                inode = d->d_inode;
 
772
                if (d != dentry) {
 
773
                        //i_lock(inode);
 
774
                        di_write_lock_child(d);
 
775
                }
 
776
 
 
777
                /* someone might update our dentry while we were sleeping */
 
778
                if (AufsGenOlder(au_digen(d), sgen)) {
 
779
                        di_read_lock_parent(parent, AUFS_I_RLOCK);
 
780
                        /* returns a number of positive dentries */
 
781
                        err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
 
782
                        //err = -1;
 
783
                        if (err >= 0)
 
784
                                err = au_refresh_hinode(inode, d);
 
785
                        //err = -1;
 
786
                        di_read_unlock(parent, AUFS_I_RLOCK);
 
787
                }
 
788
 
 
789
                if (d != dentry) {
 
790
                        di_write_unlock(d);
 
791
                        //i_unlock(inode);
 
792
                }
 
793
                if (unlikely(err))
 
794
                        break;
 
795
        }
 
796
 
 
797
        TraceErr(err);
 
798
        return err;
 
799
}
 
800
 
 
801
/*
 
802
 * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise.
 
803
 * nfsd passes NULL as nameidata.
 
804
 */
 
805
static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 
806
{
 
807
        int valid, sgen, err, do_udba;
 
808
        struct super_block *sb;
 
809
        struct inode *inode;
 
810
 
 
811
        LKTRTrace("dentry %.*s\n", DLNPair(dentry));
 
812
        if (nd && nd->dentry)
 
813
                LKTRTrace("nd %.*s\n", DLNPair(nd->dentry));
 
814
        //dir case: DEBUG_ON(dentry->d_parent != nd->dentry);
 
815
        //remove failure case: DEBUG_ON(!IS_ROOT(dentry) && d_unhashed(dentry));
 
816
        DEBUG_ON(!dentry->d_fsdata);
 
817
        //DbgDentry(dentry);
 
818
 
 
819
        err = -EINVAL;
 
820
        inode = dentry->d_inode;
 
821
        //DbgInode(inode);
 
822
        sb = dentry->d_sb;
 
823
        si_read_lock(sb);
 
824
        sgen = au_sigen(sb);
 
825
        if (au_digen(dentry) == sgen)
 
826
                di_read_lock_child(dentry, !AUFS_I_RLOCK);
 
827
        else {
 
828
                DEBUG_ON(IS_ROOT(dentry));
 
829
#ifdef ForceInotify
 
830
                Dbg("UDBA or digen, %.*s\n", DLNPair(dentry));
 
831
#endif
 
832
                //i_lock(inode);
 
833
                di_write_lock_child(dentry);
 
834
                if (inode)
 
835
                        err = au_reval_dpath(dentry, sgen);
 
836
                //err = -1;
 
837
                di_downgrade_lock(dentry, AUFS_I_RLOCK);
 
838
                //i_unlock(inode);
 
839
                if (unlikely(err))
 
840
                        goto out;
 
841
                ii_read_unlock(inode);
 
842
                DEBUG_ON(au_iigen(inode) != sgen);
 
843
        }
 
844
 
 
845
        if (inode) {
 
846
                if (au_iigen(inode) == sgen)
 
847
                        ii_read_lock_child(inode);
 
848
                else {
 
849
                        DEBUG_ON(IS_ROOT(dentry));
 
850
#ifdef ForceInotify
 
851
                        Dbg("UDBA or survived, %.*s\n", DLNPair(dentry));
 
852
#endif
 
853
                        ii_write_lock_child(inode);
 
854
                        err = au_refresh_hinode(inode, dentry);
 
855
                        ii_downgrade_lock(inode);
 
856
                        if (unlikely(err))
 
857
                                goto out;
 
858
                        DEBUG_ON(au_iigen(inode) != sgen);
 
859
                }
 
860
        }
 
861
 
 
862
#if 0 // fix it
 
863
        /* parent dir i_nlink is not updated in the case of setattr */
 
864
        if (S_ISDIR(inode->i_mode)) {
 
865
                i_lock(inode);
 
866
                ii_write_lock(inode);
 
867
                au_cpup_attr_nlink(inode);
 
868
                ii_write_unlock(inode);
 
869
                i_unlock(inode);
 
870
        }
 
871
#endif
 
872
 
 
873
        err = -EINVAL;
 
874
        do_udba = !au_flag_test(sb, AuFlag_UDBA_NONE);
 
875
        if (do_udba && inode && ibstart(inode) >= 0
 
876
            && au_test_higen(inode, au_h_iptr(inode)))
 
877
                goto out;
 
878
        err = h_d_revalidate(dentry, nd, do_udba);
 
879
        //err = -1;
 
880
 
 
881
 out:
 
882
        aufs_read_unlock(dentry, AUFS_I_RLOCK);
 
883
        TraceErr(err);
 
884
        valid = !err;
 
885
        //au_debug_on();
 
886
        if (!valid)
 
887
                LKTRTrace("%.*s invalid\n", DLNPair(dentry));
 
888
        //au_debug_off();
 
889
        return valid;
 
890
}
 
891
 
 
892
static void aufs_d_release(struct dentry *dentry)
 
893
{
 
894
        struct aufs_dinfo *dinfo;
 
895
        aufs_bindex_t bend, bindex;
 
896
 
 
897
        LKTRTrace("%.*s\n", DLNPair(dentry));
 
898
        DEBUG_ON(!d_unhashed(dentry));
 
899
 
 
900
        dinfo = dentry->d_fsdata;
 
901
        if (unlikely(!dinfo))
 
902
                return;
 
903
 
 
904
        /* dentry may not be revalidated */
 
905
        bindex = dinfo->di_bstart;
 
906
        if (bindex >= 0) {
 
907
                struct aufs_hdentry *p;
 
908
                bend = dinfo->di_bend;
 
909
                DEBUG_ON(bend < bindex);
 
910
                p = dinfo->di_hdentry + bindex;
 
911
                while (bindex++ <= bend) {
 
912
                        if (p->hd_dentry)
 
913
                                hdput(p);
 
914
                        p++;
 
915
                }
 
916
        }
 
917
        kfree(dinfo->di_hdentry);
 
918
        cache_free_dinfo(dinfo);
 
919
}
 
920
 
 
921
#if 0
 
922
/* it may be called at remount time, too */
 
923
static void aufs_d_iput(struct dentry *dentry, struct inode *inode)
 
924
{
 
925
        struct super_block *sb;
 
926
 
 
927
        LKTRTrace("%.*s, i%lu\n", DLNPair(dentry), inode->i_ino);
 
928
 
 
929
        sb = dentry->d_sb;
 
930
#if 0
 
931
        si_read_lock(sb);
 
932
        if (unlikely(au_flag_test(sb, AuFlag_PLINK)
 
933
                     && au_is_plinked(sb, inode))) {
 
934
                ii_write_lock(inode);
 
935
                au_update_brange(inode, 1);
 
936
                ii_write_unlock(inode);
 
937
        }
 
938
        si_read_unlock(sb);
 
939
#endif
 
940
        iput(inode);
 
941
}
 
942
#endif
 
943
 
 
944
struct dentry_operations aufs_dop = {
 
945
        .d_revalidate   = aufs_d_revalidate,
 
946
        .d_release      = aufs_d_release
 
947
        //.d_iput               = aufs_d_iput
 
948
};