~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-08-21 14:58:54 UTC
  • mfrom: (1.2.1 upstream) (11 intrepid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20080821145854-6erljbzg007r476y
01_vserver_apparmor.dpatch: [UPDATE] Disable vserver patches on kernel 
2.6.26, because they are not needed anymore. (Closes: #495921)

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