~ubuntu-branches/ubuntu/vivid/aufs/vivid

« back to all changes in this revision

Viewing changes to fs/aufs25/whout.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2008-05-06 18:35:50 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080506183550-0b6c974kkgc46oeh
Tags: 0+20080506-1
* New upstream release, supports Kernel 2.6.25 (Closes: #479717)
* Fix building with older Kernels (Closes: #475042)
* Update the patches 01, 04 and 07 to also patch fs/aufs25

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
 * whiteout for logical deletion and opaque directory
 
21
 *
 
22
 * $Id: whout.c,v 1.3 2008/04/28 03:04:54 sfjro Exp $
 
23
 */
 
24
 
 
25
#include <linux/fs.h>
 
26
#include <linux/namei.h>
 
27
//#include <linux/random.h>
 
28
//#include <linux/security.h>
 
29
#include "aufs.h"
 
30
 
 
31
#define WH_MASK                 S_IRUGO
 
32
 
 
33
/* If a directory contains this file, then it is opaque.  We start with the
 
34
 * .wh. flag so that it is blocked by lookup.
 
35
 */
 
36
static struct qstr diropq_name = {
 
37
        .name = AUFS_WH_DIROPQ,
 
38
        .len = sizeof(AUFS_WH_DIROPQ) - 1
 
39
};
 
40
 
 
41
/*
 
42
 * generate whiteout name, which is NOT terminated by NULL.
 
43
 * @name: original d_name.name
 
44
 * @len: original d_name.len
 
45
 * @wh: whiteout qstr
 
46
 * returns zero when succeeds, otherwise error.
 
47
 * succeeded value as wh->name should be freed by au_wh_name_free().
 
48
 */
 
49
int au_wh_name_alloc(const char *name, int len, struct qstr *wh)
 
50
{
 
51
        char *p;
 
52
 
 
53
        AuDebugOn(!name || !len || !wh);
 
54
 
 
55
        if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
 
56
                return -ENAMETOOLONG;
 
57
 
 
58
        wh->len = len + AUFS_WH_PFX_LEN;
 
59
        p = kmalloc(wh->len, GFP_KERNEL);
 
60
        wh->name = p;
 
61
        //if (LktrCond) {kfree(p); wh->name = p = NULL;}
 
62
        if (p) {
 
63
                memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
 
64
                memcpy(p + AUFS_WH_PFX_LEN, name, len);
 
65
                //smp_mb();
 
66
                return 0;
 
67
        }
 
68
        return -ENOMEM;
 
69
}
 
70
 
 
71
void au_wh_name_free(struct qstr *wh)
 
72
{
 
73
        AuDebugOn(!wh || !wh->name);
 
74
        kfree(wh->name);
 
75
#ifdef CONFIG_AUFS_DEBUG
 
76
        wh->name = NULL;
 
77
#endif
 
78
}
 
79
 
 
80
/* ---------------------------------------------------------------------- */
 
81
 
 
82
/*
 
83
 * test if the @wh_name exists under @h_parent.
 
84
 * @try_sio specifies the necessary of super-io.
 
85
 */
 
86
int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
 
87
               struct au_ndx *ndx)
 
88
{
 
89
        int err;
 
90
        struct dentry *wh_dentry;
 
91
        struct inode *h_dir;
 
92
        unsigned int flags;
 
93
 
 
94
        LKTRTrace("%.*s/%.*s, ndx{%p, 0x%x}\n", AuDLNPair(h_parent),
 
95
                  wh_name->len, wh_name->name, ndx->nfsmnt, ndx->flags);
 
96
        h_dir = h_parent->d_inode;
 
97
        AuDebugOn(!S_ISDIR(h_dir->i_mode));
 
98
 
 
99
        flags = 0;
 
100
        if (ndx && ndx->nd) {
 
101
                flags = ndx->nd->flags;
 
102
                ndx->nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE);
 
103
        }
 
104
 
 
105
        if (!try_sio)
 
106
                wh_dentry = au_lkup_one(wh_name->name, h_parent,
 
107
                                        wh_name->len, ndx);
 
108
        else
 
109
                wh_dentry = au_sio_lkup_one(wh_name->name, h_parent,
 
110
                                            wh_name->len, ndx);
 
111
        if (flags)
 
112
                ndx->nd->flags = flags;
 
113
        //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
 
114
        err = PTR_ERR(wh_dentry);
 
115
        if (IS_ERR(wh_dentry))
 
116
                goto out;
 
117
 
 
118
        err = 0;
 
119
        if (!wh_dentry->d_inode)
 
120
                goto out_wh; /* success */
 
121
 
 
122
        err = 1;
 
123
        if (S_ISREG(wh_dentry->d_inode->i_mode))
 
124
                goto out_wh; /* success */
 
125
 
 
126
        err = -EIO;
 
127
        AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
 
128
                AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
 
129
 
 
130
 out_wh:
 
131
        dput(wh_dentry);
 
132
 out:
 
133
        AuTraceErr(err);
 
134
        return err;
 
135
}
 
136
 
 
137
/*
 
138
 * test if the @h_dentry sets opaque or not.
 
139
 */
 
140
int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx)
 
141
{
 
142
        int err, try_sio;
 
143
        struct inode *h_dir;
 
144
 
 
145
        LKTRTrace("dentry %.*s\n", AuDLNPair(h_dentry));
 
146
        h_dir = h_dentry->d_inode;
 
147
        AuDebugOn(!S_ISDIR(h_dir->i_mode));
 
148
 
 
149
        try_sio = au_test_h_perm_sio(h_dir, MAY_EXEC,
 
150
                                     au_ftest_ndx(ndx->flags, DLGT));
 
151
        err = au_wh_test(h_dentry, &diropq_name, try_sio, ndx);
 
152
        AuTraceErr(err);
 
153
        return err;
 
154
}
 
155
 
 
156
/*
 
157
 * returns a negative dentry whose name is unique and temporary.
 
158
 */
 
159
struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
 
160
                             struct au_ndx *ndx)
 
161
{
 
162
#define HEX_LEN 4
 
163
        struct dentry *dentry;
 
164
        int len, i;
 
165
        char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
 
166
                     + HEX_LEN + 1], *name, *p;
 
167
        static unsigned char cnt;
 
168
 
 
169
        LKTRTrace("hp %.*s, prefix %.*s\n",
 
170
                  AuDLNPair(h_parent), prefix->len, prefix->name);
 
171
        AuDebugOn(!h_parent->d_inode);
 
172
 
 
173
        name = defname;
 
174
        len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
 
175
        if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
 
176
                dentry = ERR_PTR(-ENAMETOOLONG);
 
177
                if (unlikely(len >= PATH_MAX))
 
178
                        goto out;
 
179
                dentry = ERR_PTR(-ENOMEM);
 
180
                name = kmalloc(len + 1, GFP_KERNEL);
 
181
                //if (LktrCond) {kfree(name); name = NULL;}
 
182
                if (unlikely(!name))
 
183
                        goto out;
 
184
        }
 
185
 
 
186
        /* doubly whiteout-ed */
 
187
        memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
 
188
        p = name + AUFS_WH_PFX_LEN * 2;
 
189
        memcpy(p, prefix->name, prefix->len);
 
190
        p += prefix->len;
 
191
        *p++ = '.';
 
192
        AuDebugOn(name + len + 1 - p <= HEX_LEN);
 
193
 
 
194
        for (i = 0; i < 3; i++) {
 
195
                sprintf(p, "%.*d", HEX_LEN, cnt++);
 
196
                dentry = au_sio_lkup_one(name, h_parent, len, ndx);
 
197
                //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
 
198
                if (IS_ERR(dentry) || !dentry->d_inode)
 
199
                        goto out_name;
 
200
                dput(dentry);
 
201
        }
 
202
        /* AuWarn("could not get random name\n"); */
 
203
        dentry = ERR_PTR(-EEXIST);
 
204
        AuDbg("%.*s\n", len, name);
 
205
        BUG();
 
206
 
 
207
 out_name:
 
208
        if (unlikely(name != defname))
 
209
                kfree(name);
 
210
 out:
 
211
        AuTraceErrPtr(dentry);
 
212
        return dentry;
 
213
#undef HEX_LEN
 
214
}
 
215
 
 
216
/*
 
217
 * rename the @dentry of @bindex to the whiteouted temporary name.
 
218
 */
 
219
int au_whtmp_ren(struct inode *dir, struct dentry *dentry, aufs_bindex_t bindex,
 
220
                 int noself)
 
221
{
 
222
        int err, dlgt;
 
223
        struct inode *h_dir;
 
224
        struct dentry *h_dentry, *h_parent, *tmp_dentry;
 
225
        struct super_block *sb;
 
226
        unsigned int mnt_flags;
 
227
        struct au_hin_ignore ign;
 
228
        struct vfsub_args vargs;
 
229
        struct au_ndx ndx = {
 
230
                .flags  = 0,
 
231
                .nd     = NULL,
 
232
                //.br   = NULL
 
233
        };
 
234
 
 
235
        LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
 
236
        h_dentry = au_h_dptr(dentry, bindex);
 
237
        AuDebugOn(!h_dentry || !h_dentry->d_inode);
 
238
        h_parent = h_dentry->d_parent; /* dir inode is locked */
 
239
        h_dir = h_parent->d_inode;
 
240
        IMustLock(h_dir);
 
241
 
 
242
        sb = dentry->d_sb;
 
243
        mnt_flags = au_mntflags(sb);
 
244
        dlgt = !!au_opt_test_dlgt(mnt_flags);
 
245
        if (unlikely(dlgt))
 
246
                au_fset_ndx(ndx.flags, DLGT);
 
247
        ndx.nfsmnt = au_nfsmnt(sb, bindex);
 
248
        tmp_dentry = au_whtmp_lkup(h_parent, &h_dentry->d_name, &ndx);
 
249
        //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
 
250
        err = PTR_ERR(tmp_dentry);
 
251
        if (!IS_ERR(tmp_dentry)) {
 
252
                /* under the same dir, no need to lock_rename() */
 
253
                vfsub_args_init(&vargs, &ign, dlgt, 0);
 
254
                AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
 
255
                if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY) && !noself))
 
256
                        vfsub_ign_hinode(&vargs, IN_MOVE_SELF,
 
257
                                         au_hi(dentry->d_inode, bindex));
 
258
                err = vfsub_rename(h_dir, h_dentry, h_dir, tmp_dentry, &vargs);
 
259
                //if (LktrCond) err = -1; //unavailable
 
260
                AuTraceErr(err);
 
261
                dput(tmp_dentry);
 
262
        }
 
263
 
 
264
        AuTraceErr(err);
 
265
        return err;
 
266
}
 
267
 
 
268
/* ---------------------------------------------------------------------- */
 
269
 
 
270
static int do_unlink_wh(struct inode *h_dir, struct dentry *wh_dentry,
 
271
                        struct inode *dir, int dlgt)
 
272
{
 
273
        struct vfsub_args vargs;
 
274
 
 
275
        LKTRTrace("hi%lu, wh %.*s\n", h_dir->i_ino, AuDLNPair(wh_dentry));
 
276
        AuDebugOn(!wh_dentry->d_inode || !S_ISREG(wh_dentry->d_inode->i_mode));
 
277
 
 
278
        /*
 
279
         * forces superio when the dir has a sticky bit.
 
280
         * this may be a violation of unix fs semantics.
 
281
         */
 
282
        vfsub_args_init(&vargs, NULL, dlgt,
 
283
                        (h_dir->i_mode & S_ISVTX)
 
284
                        && wh_dentry->d_inode->i_uid != current->fsuid);
 
285
        return vfsub_unlink(h_dir, wh_dentry, &vargs);
 
286
}
 
287
 
 
288
int au_wh_unlink_dentry(struct inode *h_dir, struct dentry *wh_dentry,
 
289
                        struct dentry *dentry, struct inode *dir, int dlgt)
 
290
{
 
291
        int err;
 
292
 
 
293
        LKTRTrace("hi%lu, wh %.*s, d %p\n", h_dir->i_ino,
 
294
                  AuDLNPair(wh_dentry), dentry);
 
295
        AuDebugOn((dentry && au_dbwh(dentry) < 0)
 
296
                  || !wh_dentry->d_inode
 
297
                  || !S_ISREG(wh_dentry->d_inode->i_mode));
 
298
 
 
299
        err = do_unlink_wh(h_dir, wh_dentry, dir, dlgt);
 
300
        //if (LktrCond) err = -1; // unavailable
 
301
        if (!err && dentry)
 
302
                au_set_dbwh(dentry, -1);
 
303
 
 
304
        AuTraceErr(err);
 
305
        return err;
 
306
}
 
307
 
 
308
static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
 
309
                          struct inode *dir, struct au_ndx *ndx)
 
310
{
 
311
        int err;
 
312
        struct inode *h_dir;
 
313
        struct dentry *h_dentry;
 
314
 
 
315
        LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(wh));
 
316
        h_dir = h_parent->d_inode;
 
317
 
 
318
        /* au_test_h_perm() is already done */
 
319
        h_dentry = au_lkup_one(wh->name, h_parent, wh->len, ndx);
 
320
        //if (LktrCond) {dput(h_dentry); h_dentry = ERR_PTR(-1);}
 
321
        if (!IS_ERR(h_dentry)) {
 
322
                err = 0;
 
323
                if (h_dentry->d_inode && S_ISREG(h_dentry->d_inode->i_mode))
 
324
                        err = do_unlink_wh(h_dir, h_dentry, dir,
 
325
                                           au_ftest_ndx(ndx->flags, DLGT));
 
326
                dput(h_dentry);
 
327
        } else
 
328
                err = PTR_ERR(h_dentry);
 
329
 
 
330
        AuTraceErr(err);
 
331
        return err;
 
332
}
 
333
 
 
334
/* ---------------------------------------------------------------------- */
 
335
 
 
336
static void clean_wh(struct inode *h_dir, struct dentry *wh)
 
337
{
 
338
        int err;
 
339
        struct vfsub_args vargs;
 
340
 
 
341
        AuTraceEnter();
 
342
 
 
343
        if (wh->d_inode) {
 
344
                vfsub_args_init(&vargs, NULL, 0, 0);
 
345
                err = vfsub_unlink(h_dir, wh, &vargs);
 
346
                if (unlikely(err))
 
347
                        AuWarn("failed unlink %.*s (%d), ignored.\n",
 
348
                               AuDLNPair(wh), err);
 
349
        }
 
350
}
 
351
 
 
352
static void clean_plink(struct inode *h_dir, struct dentry *plink)
 
353
{
 
354
        int err;
 
355
        struct vfsub_args vargs;
 
356
 
 
357
        AuTraceEnter();
 
358
 
 
359
        if (plink->d_inode) {
 
360
                vfsub_args_init(&vargs, NULL, 0, 0);
 
361
                err = vfsub_rmdir(h_dir, plink, &vargs);
 
362
                if (unlikely(err))
 
363
                        AuWarn("failed rmdir %.*s (%d), ignored.\n",
 
364
                               AuDLNPair(plink), err);
 
365
        }
 
366
}
 
367
 
 
368
static int test_linkable(struct inode *h_dir)
 
369
{
 
370
        if (h_dir->i_op && h_dir->i_op->link)
 
371
                return 0;
 
372
        return -ENOSYS;
 
373
}
 
374
 
 
375
static int plink_dir(struct inode *h_dir, struct dentry *plink)
 
376
{
 
377
        int err;
 
378
 
 
379
        err = -EEXIST;
 
380
        if (!plink->d_inode) {
 
381
                int mode = S_IRWXU;
 
382
                if (unlikely(au_test_nfs(plink->d_sb)))
 
383
                        mode |= S_IXUGO;
 
384
                err = vfsub_mkdir(h_dir, plink, mode, /*dlgt*/0);
 
385
        } else if (S_ISDIR(plink->d_inode->i_mode))
 
386
                err = 0;
 
387
        else
 
388
                AuErr("unknown %.*s exists\n", AuDLNPair(plink));
 
389
 
 
390
        return err;
 
391
}
 
392
 
 
393
/*
 
394
 * initialize the whiteout base file/dir for @br.
 
395
 */
 
396
int au_wh_init(struct dentry *h_root, struct au_branch *br,
 
397
               struct vfsmount *nfsmnt, struct super_block *sb)
 
398
{
 
399
        int err;
 
400
        struct dentry *wh, *plink;
 
401
        struct inode *h_dir;
 
402
        static struct qstr base_name[] = {
 
403
                {
 
404
                        .name   = AUFS_WH_BASENAME,
 
405
                        .len    = sizeof(AUFS_WH_BASENAME) - 1
 
406
                },
 
407
                {
 
408
                        .name   = AUFS_WH_PLINKDIR,
 
409
                        .len    = sizeof(AUFS_WH_PLINKDIR) - 1
 
410
                }
 
411
        };
 
412
        struct au_ndx ndx = {
 
413
                .nfsmnt = nfsmnt,
 
414
                .flags  = 0, /* always no dlgt */
 
415
                .nd     = NULL,
 
416
                //.br   = NULL
 
417
        };
 
418
        const int do_plink = au_opt_test(au_mntflags(sb), PLINK);
 
419
 
 
420
        LKTRTrace("nfsmnt %p\n", nfsmnt);
 
421
        BrWhMustWriteLock(br);
 
422
        SiMustWriteLock(sb);
 
423
        h_dir = h_root->d_inode;
 
424
 
 
425
        /* doubly whiteouted */
 
426
        wh = au_wh_lkup(h_root, base_name + 0, &ndx);
 
427
        //if (LktrCond) {dput(wh); wh = ERR_PTR(-1);}
 
428
        err = PTR_ERR(wh);
 
429
        if (IS_ERR(wh))
 
430
                goto out;
 
431
        AuDebugOn(br->br_wh && br->br_wh != wh);
 
432
 
 
433
        plink = au_wh_lkup(h_root, base_name + 1, &ndx);
 
434
        err = PTR_ERR(plink);
 
435
        if (IS_ERR(plink))
 
436
                goto out_dput_wh;
 
437
        AuDebugOn(br->br_plink && br->br_plink != plink);
 
438
 
 
439
        dput(br->br_wh);
 
440
        dput(br->br_plink);
 
441
        br->br_wh = NULL;
 
442
        br->br_plink = NULL;
 
443
 
 
444
        err = 0;
 
445
        switch (br->br_perm) {
 
446
        case AuBr_RR:
 
447
        case AuBr_RO:
 
448
        case AuBr_RRWH:
 
449
        case AuBr_ROWH:
 
450
                clean_wh(h_dir, wh);
 
451
                clean_plink(h_dir, plink);
 
452
                break;
 
453
 
 
454
        case AuBr_RWNoLinkWH:
 
455
                clean_wh(h_dir, wh);
 
456
                if (do_plink) {
 
457
                        err = test_linkable(h_dir);
 
458
                        if (unlikely(err))
 
459
                                goto out_nolink;
 
460
 
 
461
                        err = plink_dir(h_dir, plink);
 
462
                        if (unlikely(err))
 
463
                                goto out_err;
 
464
                        br->br_plink = dget(plink);
 
465
                } else
 
466
                        clean_plink(h_dir, plink);
 
467
                break;
 
468
 
 
469
        case AuBr_RW:
 
470
                /*
 
471
                 * for the moment, aufs supports the branch filesystem
 
472
                 * which does not support link(2).
 
473
                 * testing on FAT which does not support i_op->setattr() fully
 
474
                 * either, copyup failed.
 
475
                 * finally, such filesystem will not be used as the writable
 
476
                 * branch.
 
477
                 */
 
478
                err = test_linkable(h_dir);
 
479
                if (unlikely(err))
 
480
                        goto out_nolink;
 
481
 
 
482
                err = -EEXIST;
 
483
                if (!wh->d_inode)
 
484
                        err = au_h_create(h_dir, wh, WH_MASK, /*dlgt*/0,
 
485
                                          /*nd*/NULL, nfsmnt);
 
486
                else if (S_ISREG(wh->d_inode->i_mode))
 
487
                        err = 0;
 
488
                else
 
489
                        AuErr("unknown %.*s/%.*s exists\n",
 
490
                              AuDLNPair(h_root), AuDLNPair(wh));
 
491
                if (unlikely(err))
 
492
                        goto out_err;
 
493
 
 
494
                if (do_plink) {
 
495
                        err = plink_dir(h_dir, plink);
 
496
                        if (unlikely(err))
 
497
                                goto out_err;
 
498
                        br->br_plink = dget(plink);
 
499
                } else
 
500
                        clean_plink(h_dir, plink);
 
501
                br->br_wh = dget(wh);
 
502
                break;
 
503
 
 
504
        default:
 
505
                BUG();
 
506
        }
 
507
 
 
508
 out_dput:
 
509
        dput(plink);
 
510
 out_dput_wh:
 
511
        dput(wh);
 
512
 out:
 
513
        AuTraceErr(err);
 
514
        return err;
 
515
 out_nolink:
 
516
        AuErr("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
 
517
              AuDLNPair(h_root));
 
518
        goto out_dput;
 
519
 out_err:
 
520
        AuErr("an error(%d) on the writable branch %.*s(%s)\n",
 
521
              err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
 
522
        goto out_dput;
 
523
}
 
524
 
 
525
struct reinit_br_wh {
 
526
        struct super_block *sb;
 
527
        struct au_branch *br;
 
528
};
 
529
 
 
530
static void reinit_br_wh(void *arg)
 
531
{
 
532
        int err;
 
533
        struct reinit_br_wh *a = arg;
 
534
        struct inode *h_dir, *dir;
 
535
        struct dentry *h_root;
 
536
        aufs_bindex_t bindex;
 
537
        struct vfsub_args vargs;
 
538
 
 
539
        AuTraceEnter();
 
540
        AuDebugOn(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
 
541
 
 
542
        err = 0;
 
543
        /* big aufs lock */
 
544
        si_write_lock(a->sb);
 
545
        if (unlikely(!au_br_writable(a->br->br_perm)))
 
546
                goto out;
 
547
        bindex = au_br_index(a->sb, a->br->br_id);
 
548
        if (unlikely(bindex < 0))
 
549
                goto out;
 
550
 
 
551
        dir = a->sb->s_root->d_inode;
 
552
        h_root = dget_parent(a->br->br_wh);
 
553
        h_dir = h_root->d_inode;
 
554
        AuDebugOn(!h_dir->i_op || !h_dir->i_op->link);
 
555
        vfsub_args_init(&vargs, NULL, /*dlgt*/0, 0);
 
556
        au_hdir_lock(h_dir, dir, bindex);
 
557
#if 0
 
558
        revalidate h_wh
 
559
#endif
 
560
        br_wh_write_lock(a->br);
 
561
        err = vfsub_unlink(h_dir, a->br->br_wh, &vargs);
 
562
        //if (LktrCond) err = -1;
 
563
        dput(a->br->br_wh);
 
564
        a->br->br_wh = NULL;
 
565
        if (!err)
 
566
                err = au_wh_init(h_root, a->br, au_do_nfsmnt(a->br->br_mnt),
 
567
                                 a->sb);
 
568
        br_wh_write_unlock(a->br);
 
569
        au_hdir_unlock(h_dir, dir, bindex);
 
570
        dput(h_root);
 
571
 
 
572
 out:
 
573
        atomic_dec_return(&a->br->br_wh_running);
 
574
        au_br_put(a->br);
 
575
        si_write_unlock(a->sb);
 
576
        kfree(arg);
 
577
        if (unlikely(err))
 
578
                AuIOErr("err %d\n", err);
 
579
}
 
580
 
 
581
static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
 
582
{
 
583
        int do_dec, wkq_err;
 
584
        struct reinit_br_wh *arg;
 
585
 
 
586
        do_dec = 1;
 
587
        if (atomic_inc_return(&br->br_wh_running) != 1)
 
588
                goto out;
 
589
 
 
590
        /* ignore ENOMEM */
 
591
        arg = kmalloc(sizeof(*arg), GFP_TEMPORARY);
 
592
        if (arg) {
 
593
                /*
 
594
                 * dec(wh_running), kfree(arg) and au_br_put()
 
595
                 * in reinit function
 
596
                 */
 
597
                arg->sb = sb;
 
598
                arg->br = br;
 
599
                au_br_get(br);
 
600
                wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*dlgt*/0);
 
601
                if (unlikely(wkq_err)) {
 
602
                        atomic_dec_return(&br->br_wh_running);
 
603
                        au_br_put(br);
 
604
                        kfree(arg);
 
605
                }
 
606
                do_dec = 0;
 
607
        }
 
608
 
 
609
 out:
 
610
        if (do_dec)
 
611
                atomic_dec_return(&br->br_wh_running);
 
612
}
 
613
 
 
614
/*
 
615
 * create the whiteout @wh.
 
616
 */
 
617
static int link_or_create_wh(struct dentry *wh, struct super_block *sb,
 
618
                             aufs_bindex_t bindex, struct inode *dir)
 
619
{
 
620
        int err, dlgt;
 
621
        struct au_branch *br;
 
622
        struct dentry *h_parent;
 
623
        struct inode *h_dir;
 
624
 
 
625
        LKTRTrace("%.*s\n", AuDLNPair(wh));
 
626
        SiMustReadLock(sb);
 
627
        h_parent = wh->d_parent; /* dir inode is locked */
 
628
        h_dir = h_parent->d_inode;
 
629
        IMustLock(h_dir);
 
630
 
 
631
        dlgt = !!au_opt_test_dlgt(au_mntflags(sb));
 
632
        br = au_sbr(sb, bindex);
 
633
        br_wh_read_lock(br);
 
634
        if (br->br_wh) {
 
635
                err = vfsub_link(br->br_wh, h_dir, wh, dlgt);
 
636
                if (!err || err != -EMLINK)
 
637
                        goto out;
 
638
 
 
639
                /* link count full. re-initialize br_wh. */
 
640
                kick_reinit_br_wh(sb, br);
 
641
        }
 
642
 
 
643
        /* return this error in this context */
 
644
        err = au_h_create(h_dir, wh, WH_MASK, dlgt, /*nd*/NULL,
 
645
                          au_do_nfsmnt(br->br_mnt));
 
646
 
 
647
 out:
 
648
        br_wh_read_unlock(br);
 
649
        AuTraceErr(err);
 
650
        return err;
 
651
}
 
652
 
 
653
/* ---------------------------------------------------------------------- */
 
654
 
 
655
/*
 
656
 * create or remove the diropq.
 
657
 */
 
658
static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
 
659
                                unsigned int flags)
 
660
{
 
661
        struct dentry *opq_dentry, *h_dentry;
 
662
        struct inode *h_dir;
 
663
        int err, dlgt;
 
664
        struct super_block *sb;
 
665
        struct au_ndx ndx = {
 
666
                .flags  = 0,
 
667
                .nd     = NULL,
 
668
                //.br   = NULL
 
669
        };
 
670
 
 
671
        LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
 
672
                  AuDLNPair(dentry), bindex, flags);
 
673
        h_dentry = au_h_dptr(dentry, bindex);
 
674
        AuDebugOn(!h_dentry);
 
675
        h_dir = h_dentry->d_inode;
 
676
        AuDebugOn(!h_dir || !S_ISDIR(h_dir->i_mode));
 
677
 
 
678
        /* already checked by au_test_h_perm(). */
 
679
        sb = dentry->d_sb;
 
680
        ndx.nfsmnt = au_nfsmnt(sb, bindex);
 
681
        dlgt = 0;
 
682
        if (unlikely(au_ftest_diropq(flags, DLGT))) {
 
683
                dlgt = 1;
 
684
                au_fset_ndx(ndx.flags, DLGT);
 
685
        }
 
686
        opq_dentry = au_lkup_one(diropq_name.name, h_dentry, diropq_name.len,
 
687
                                 &ndx);
 
688
        //if (LktrCond) {dput(opq_dentry); opq_dentry = ERR_PTR(-1);}
 
689
        if (IS_ERR(opq_dentry))
 
690
                goto out;
 
691
 
 
692
        if (au_ftest_diropq(flags, CREATE)) {
 
693
                AuDebugOn(opq_dentry->d_inode);
 
694
                err = link_or_create_wh(opq_dentry, sb, bindex,
 
695
                                        dentry->d_inode);
 
696
                //if (LktrCond) {vfs_unlink(h_dir, opq_dentry); err = -1;}
 
697
                if (!err) {
 
698
                        au_set_dbdiropq(dentry, bindex);
 
699
                        goto out; /* success */
 
700
                }
 
701
        } else {
 
702
                AuDebugOn(/* !S_ISDIR(dentry->d_inode->i_mode)
 
703
                           * ||  */!opq_dentry->d_inode);
 
704
                err = do_unlink_wh(h_dir, opq_dentry, dentry->d_inode, dlgt);
 
705
                //if (LktrCond) err = -1;
 
706
                if (!err)
 
707
                        au_set_dbdiropq(dentry, -1);
 
708
        }
 
709
        dput(opq_dentry);
 
710
        opq_dentry = ERR_PTR(err);
 
711
 
 
712
 out:
 
713
        AuTraceErrPtr(opq_dentry);
 
714
        return opq_dentry;
 
715
}
 
716
 
 
717
struct do_diropq_args {
 
718
        struct dentry **errp;
 
719
        struct dentry *dentry;
 
720
        aufs_bindex_t bindex;
 
721
        unsigned int flags;
 
722
};
 
723
 
 
724
static void call_do_diropq(void *args)
 
725
{
 
726
        struct do_diropq_args *a = args;
 
727
        *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
 
728
}
 
729
 
 
730
struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
 
731
                             unsigned int flags)
 
732
{
 
733
        struct dentry *diropq, *h_dentry;
 
734
 
 
735
        LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
 
736
                  AuDLNPair(dentry), bindex, flags);
 
737
 
 
738
        h_dentry = au_h_dptr(dentry, bindex);
 
739
        if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE,
 
740
                                au_ftest_diropq(flags, DLGT)))
 
741
                diropq = do_diropq(dentry, bindex, flags);
 
742
        else {
 
743
                int wkq_err;
 
744
                struct do_diropq_args args = {
 
745
                        .errp           = &diropq,
 
746
                        .dentry         = dentry,
 
747
                        .bindex         = bindex,
 
748
                        .flags          = flags
 
749
                };
 
750
                wkq_err = au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
 
751
                if (unlikely(wkq_err))
 
752
                        diropq = ERR_PTR(wkq_err);
 
753
        }
 
754
 
 
755
        AuTraceErrPtr(diropq);
 
756
        return diropq;
 
757
}
 
758
 
 
759
/* ---------------------------------------------------------------------- */
 
760
 
 
761
/*
 
762
 * lookup whiteout dentry.
 
763
 * @h_parent: hidden parent dentry which must exist and be locked
 
764
 * @base_name: name of dentry which will be whiteouted
 
765
 * returns dentry for whiteout.
 
766
 */
 
767
struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
 
768
                          struct au_ndx *ndx)
 
769
{
 
770
        int err;
 
771
        struct qstr wh_name;
 
772
        struct dentry *wh_dentry;
 
773
 
 
774
        LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(base_name));
 
775
 
 
776
        err = au_wh_name_alloc(base_name->name, base_name->len, &wh_name);
 
777
        //if (LktrCond) {au_wh_name_free(&wh_name); err = -1;}
 
778
        wh_dentry = ERR_PTR(err);
 
779
        if (!err) {
 
780
                /* do not superio. */
 
781
                wh_dentry = au_lkup_one(wh_name.name, h_parent,
 
782
                                        wh_name.len, ndx);
 
783
                au_wh_name_free(&wh_name);
 
784
        }
 
785
        AuTraceErrPtr(wh_dentry);
 
786
        return wh_dentry;
 
787
}
 
788
 
 
789
/*
 
790
 * link/create a whiteout for @dentry on @bindex.
 
791
 */
 
792
struct dentry *au_wh_create(struct inode *dir, struct dentry *dentry,
 
793
                            aufs_bindex_t bindex, struct dentry *h_parent,
 
794
                            struct au_ndx *ndx)
 
795
{
 
796
        struct dentry *wh_dentry;
 
797
        int err;
 
798
        struct super_block *sb;
 
799
 
 
800
        LKTRTrace("%.*s/%.*s on b%d\n", AuDLNPair(h_parent),
 
801
                  AuDLNPair(dentry), bindex);
 
802
 
 
803
        sb = dentry->d_sb;
 
804
        wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, ndx);
 
805
        //au_nfsmnt(sb, bindex), need_dlgt(sb));
 
806
        //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
 
807
        if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
 
808
                err = link_or_create_wh(wh_dentry, sb, bindex, dir);
 
809
                if (!err)
 
810
                        au_set_dbwh(dentry, bindex);
 
811
                else {
 
812
                        dput(wh_dentry);
 
813
                        wh_dentry = ERR_PTR(err);
 
814
                }
 
815
        }
 
816
 
 
817
        AuTraceErrPtr(wh_dentry);
 
818
        return wh_dentry;
 
819
}
 
820
 
 
821
/* ---------------------------------------------------------------------- */
 
822
 
 
823
/* Delete all whiteouts in this directory on branch bindex. */
 
824
static int del_wh_children(struct au_nhash *whlist, struct dentry *h_parent,
 
825
                           aufs_bindex_t bindex, struct inode *inode,
 
826
                           struct au_ndx *ndx)
 
827
{
 
828
        int err, i;
 
829
        struct qstr wh_name;
 
830
        char *p;
 
831
        struct inode *h_dir;
 
832
        struct hlist_head *head;
 
833
        struct au_vdir_wh *tpos;
 
834
        struct hlist_node *pos;
 
835
        struct au_vdir_destr *str;
 
836
 
 
837
        LKTRTrace("%.*s\n", AuDLNPair(h_parent));
 
838
        h_dir = h_parent->d_inode;
 
839
        AuDebugOn(IS_RDONLY(h_dir));
 
840
        //SiMustReadLock(??);
 
841
 
 
842
        err = -ENOMEM;
 
843
        p = __getname();
 
844
        wh_name.name = p;
 
845
        //if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
 
846
        if (unlikely(!wh_name.name))
 
847
                goto out;
 
848
        memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
 
849
        p += AUFS_WH_PFX_LEN;
 
850
 
 
851
        /* already checked by au_test_h_perm(). */
 
852
        err = 0;
 
853
        for (i = 0; !err && i < AuSize_NHASH; i++) {
 
854
                head = whlist->heads + i;
 
855
                hlist_for_each_entry(tpos, pos, head, wh_hash) {
 
856
                        if (tpos->wh_bindex != bindex)
 
857
                                continue;
 
858
                        str = &tpos->wh_str;
 
859
                        if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
 
860
                                memcpy(p, str->name, str->len);
 
861
                                wh_name.len = AUFS_WH_PFX_LEN + str->len;
 
862
                                err = unlink_wh_name(h_parent, &wh_name, inode,
 
863
                                                     ndx);
 
864
                                //if (LktrCond) err = -1;
 
865
                                if (!err)
 
866
                                        continue;
 
867
                                break;
 
868
                        }
 
869
                        AuIOErr("whiteout name too long %.*s\n",
 
870
                                str->len, str->name);
 
871
                        err = -EIO;
 
872
                        break;
 
873
                }
 
874
        }
 
875
        __putname(wh_name.name);
 
876
 
 
877
 out:
 
878
        AuTraceErr(err);
 
879
        return err;
 
880
}
 
881
 
 
882
struct del_wh_children_args {
 
883
        int *errp;
 
884
        struct au_nhash *whlist;
 
885
        struct dentry *h_parent;
 
886
        aufs_bindex_t bindex;
 
887
        struct inode *inode;
 
888
        struct au_ndx *ndx;
 
889
};
 
890
 
 
891
static void call_del_wh_children(void *args)
 
892
{
 
893
        struct del_wh_children_args *a = args;
 
894
        *a->errp = del_wh_children(a->whlist, a->h_parent, a->bindex,
 
895
                                   a->inode, a->ndx);
 
896
}
 
897
 
 
898
/* ---------------------------------------------------------------------- */
 
899
 
 
900
/*
 
901
 * rmdir the whiteouted temporary named dir @h_dentry.
 
902
 * @whlist: whiteouted children.
 
903
 */
 
904
int au_whtmp_rmdir(struct dentry *h_dentry, struct au_nhash *whlist,
 
905
                   aufs_bindex_t bindex, struct inode *dir, struct inode *inode,
 
906
                   int noself)
 
907
{
 
908
        int err, dlgt;
 
909
        struct inode *h_inode, *h_dir;
 
910
        struct super_block *sb;
 
911
        unsigned int mnt_flags;
 
912
        struct au_hin_ignore ign;
 
913
        struct vfsub_args vargs;
 
914
        struct au_ndx ndx = {
 
915
                .flags  = 0,
 
916
                .nd     = NULL,
 
917
                //.br   = NULL
 
918
        };
 
919
 
 
920
        LKTRTrace("hd %.*s, b%d, i%lu\n",
 
921
                  AuDLNPair(h_dentry), bindex, dir->i_ino);
 
922
        IMustLock(dir);
 
923
        IiMustAnyLock(dir);
 
924
        h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
 
925
        IMustLock(h_dir);
 
926
 
 
927
        sb = inode->i_sb;
 
928
        mnt_flags = au_mntflags(sb);
 
929
        dlgt = !!au_opt_test_dlgt(mnt_flags);
 
930
        if (unlikely(dlgt))
 
931
                au_fset_ndx(ndx.flags, DLGT);
 
932
        ndx.nfsmnt = au_nfsmnt(sb, bindex);
 
933
        h_inode = h_dentry->d_inode;
 
934
        AuDebugOn(h_inode != au_h_iptr(inode, bindex));
 
935
        au_hdir2_lock(h_inode, inode, bindex);
 
936
 
 
937
        /*
 
938
         * someone else might change some whiteouts while we were sleeping.
 
939
         * it means this whlist may have an obsoleted entry.
 
940
         */
 
941
        if (!au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_WRITE, dlgt))
 
942
                err = del_wh_children(whlist, h_dentry, bindex, inode, &ndx);
 
943
        else {
 
944
                int wkq_err;
 
945
                /* ugly */
 
946
                unsigned int flags = ndx.flags;
 
947
                struct del_wh_children_args args = {
 
948
                        .errp           = &err,
 
949
                        .whlist         = whlist,
 
950
                        .h_parent       = h_dentry,
 
951
                        .bindex         = bindex,
 
952
                        .inode          = inode,
 
953
                        .ndx            = &ndx
 
954
                };
 
955
 
 
956
                ndx.flags = 0;
 
957
                wkq_err = au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
 
958
                if (unlikely(wkq_err))
 
959
                        err = wkq_err;
 
960
                ndx.flags = flags;
 
961
        }
 
962
        au_hdir_unlock(h_inode, inode, bindex);
 
963
 
 
964
        if (!err) {
 
965
                vfsub_args_init(&vargs, &ign, dlgt, 0);
 
966
                if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY) && !noself))
 
967
                        vfsub_ign_hinode(&vargs, IN_DELETE_SELF,
 
968
                                         au_hi(inode, bindex));
 
969
                err = vfsub_rmdir(h_dir, h_dentry, &vargs);
 
970
                //d_drop(h_dentry);
 
971
                //if (LktrCond) err = -1;
 
972
        }
 
973
 
 
974
        if (!err) {
 
975
                if (au_ibstart(dir) == bindex) {
 
976
                        au_cpup_attr_timesizes(dir);
 
977
                        //au_cpup_attr_nlink(dir);
 
978
                        drop_nlink(dir);
 
979
                }
 
980
                return 0; /* success */
 
981
        }
 
982
 
 
983
        AuWarn("failed removing %.*s(%d), ignored\n", AuDLNPair(h_dentry), err);
 
984
        return err;
 
985
}
 
986
 
 
987
static void au_whtmp_rmdir_free_args(struct au_whtmp_rmdir_args *args)
 
988
{
 
989
        dput(args->h_dentry);
 
990
        au_nhash_fin(&args->whlist);
 
991
        iput(args->inode);
 
992
        mutex_unlock(&args->dir->i_mutex);
 
993
        iput(args->dir);
 
994
        kfree(args);
 
995
}
 
996
 
 
997
static void do_rmdir_whtmp(void *args)
 
998
{
 
999
        int err;
 
1000
        struct au_whtmp_rmdir_args *a = args;
 
1001
        struct super_block *sb;
 
1002
 
 
1003
        LKTRTrace("%.*s, b%d, dir i%lu\n",
 
1004
                  AuDLNPair(a->h_dentry), a->bindex, a->dir->i_ino);
 
1005
 
 
1006
        mutex_lock(&a->dir->i_mutex);
 
1007
        sb = a->dir->i_sb;
 
1008
        //AuDbgSleep(3);
 
1009
        si_read_lock(sb, !AuLock_FLUSH);
 
1010
        err = au_test_ro(sb, a->bindex, NULL);
 
1011
        if (!err) {
 
1012
                struct dentry *h_parent = dget_parent(a->h_dentry);
 
1013
                struct inode *h_dir = h_parent->d_inode;
 
1014
 
 
1015
                ii_write_lock_child(a->inode);
 
1016
                ii_write_lock_parent(a->dir);
 
1017
                au_hdir_lock(h_dir, a->dir, a->bindex);
 
1018
#if 0
 
1019
                revalidate h_dentry
 
1020
#endif
 
1021
                err = au_whtmp_rmdir(a->h_dentry, &a->whlist, a->bindex,
 
1022
                                     a->dir, a->inode, a->noself);
 
1023
                au_hdir_unlock(h_dir, a->dir, a->bindex);
 
1024
                ii_write_unlock(a->dir);
 
1025
                ii_write_unlock(a->inode);
 
1026
                dput(h_parent);
 
1027
        }
 
1028
        si_read_unlock(sb);
 
1029
        au_whtmp_rmdir_free_args(a);
 
1030
        if (unlikely(err))
 
1031
                AuIOErr("err %d\n", err);
 
1032
}
 
1033
 
 
1034
void au_whtmp_kick_rmdir(struct dentry *h_dentry, struct au_nhash *whlist,
 
1035
                         aufs_bindex_t bindex, struct inode *dir,
 
1036
                         struct inode *inode, int noself,
 
1037
                         struct au_whtmp_rmdir_args *args)
 
1038
{
 
1039
        int wkq_err;
 
1040
 
 
1041
        LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
 
1042
        IMustLock(dir);
 
1043
 
 
1044
        /* all post-process will be done in do_rmdir_whtmp(). */
 
1045
        args->h_dentry = dget(h_dentry);
 
1046
        au_nhash_init(&args->whlist);
 
1047
        au_nhash_move(&args->whlist, whlist);
 
1048
        args->bindex = bindex;
 
1049
        args->dir = igrab(dir);
 
1050
        args->inode = igrab(inode);
 
1051
        args->noself = noself;
 
1052
        wkq_err = au_wkq_nowait(do_rmdir_whtmp, args, dir->i_sb, /*dlgt*/0);
 
1053
        if (unlikely(wkq_err)) {
 
1054
                AuWarn("rmdir error %.*s (%d), ignored\n",
 
1055
                       AuDLNPair(h_dentry), wkq_err);
 
1056
                au_whtmp_rmdir_free_args(args);
 
1057
        }
 
1058
}