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

« back to all changes in this revision

Viewing changes to fs/aufs25/i_op_del.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005-2008 Junjiro Okajima
 
3
 *
 
4
 * This program, aufs is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 */
 
18
 
 
19
/*
 
20
 * inode operations (del entry)
 
21
 *
 
22
 * $Id: i_op_del.c,v 1.4 2008/05/04 23:54:53 sfjro Exp $
 
23
 */
 
24
 
 
25
#include "aufs.h"
 
26
 
 
27
/* returns,
 
28
 * 0: wh is unnecessary
 
29
 * plus: wh is necessary
 
30
 * minus: error
 
31
 */
 
32
int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
 
33
                      struct dentry *locked)
 
34
{
 
35
        int need_wh, err;
 
36
        aufs_bindex_t bstart;
 
37
        struct dentry *h_dentry;
 
38
        struct super_block *sb;
 
39
 
 
40
        LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
 
41
                  AuDLNPair(dentry), isdir, *bcpup, locked);
 
42
        sb = dentry->d_sb;
 
43
 
 
44
        bstart = au_dbstart(dentry);
 
45
        LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
 
46
        h_dentry = au_h_dptr(dentry, bstart);
 
47
        if (*bcpup < 0) {
 
48
                *bcpup = bstart;
 
49
                if (au_test_ro(sb, bstart, dentry->d_inode)) {
 
50
                        err = AuWbrCopyup(au_sbi(sb), dentry);
 
51
                        *bcpup = err;
 
52
                        //err = -1;
 
53
                        if (unlikely(err < 0))
 
54
                                goto out;
 
55
                }
 
56
        } else
 
57
                AuDebugOn(bstart < *bcpup
 
58
                          || au_test_ro(sb, *bcpup, dentry->d_inode));
 
59
        LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
 
60
 
 
61
        if (*bcpup != bstart) {
 
62
                err = au_cpup_dirs(dentry, *bcpup, locked);
 
63
                //err = -1;
 
64
                if (unlikely(err))
 
65
                        goto out;
 
66
                need_wh = 1;
 
67
        } else {
 
68
                //struct nameidata nd;
 
69
                aufs_bindex_t old_bend, new_bend, bdiropq = -1;
 
70
                old_bend = au_dbend(dentry);
 
71
                if (isdir) {
 
72
                        bdiropq = au_dbdiropq(dentry);
 
73
                        au_set_dbdiropq(dentry, -1);
 
74
                }
 
75
                need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
 
76
                                         /*nd*/NULL);
 
77
                err = need_wh;
 
78
                //err = -1;
 
79
                if (isdir)
 
80
                        au_set_dbdiropq(dentry, bdiropq);
 
81
                if (unlikely(err < 0))
 
82
                        goto out;
 
83
                new_bend = au_dbend(dentry);
 
84
                if (!need_wh && old_bend != new_bend) {
 
85
                        au_set_h_dptr(dentry, new_bend, NULL);
 
86
                        au_set_dbend(dentry, old_bend);
 
87
#if 0 // remove this?
 
88
                } else if (!au_h_dptr(dentry, new_bend)->d_inode) {
 
89
                        LKTRTrace("negative\n");
 
90
                        au_set_h_dptr(dentry, new_bend, NULL);
 
91
                        au_set_dbend(dentry, old_bend);
 
92
                        need_wh = 0;
 
93
#endif
 
94
                }
 
95
        }
 
96
        LKTRTrace("need_wh %d\n", need_wh);
 
97
        err = need_wh;
 
98
 
 
99
 out:
 
100
        AuTraceErr(err);
 
101
        return err;
 
102
}
 
103
 
 
104
/*
 
105
 * simple tests for the removal inode operations.
 
106
 * following the checks in vfs, plus the parent-child relationship.
 
107
 */
 
108
int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
 
109
               struct dentry *h_parent, int isdir, struct au_ndx *ndx)
 
110
{
 
111
        int err, exist;
 
112
        struct super_block *sb;
 
113
        struct dentry *h_dentry;
 
114
        struct inode *h_inode;
 
115
        umode_t h_mode;
 
116
 
 
117
        LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
 
118
                  AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);
 
119
 
 
120
        sb = dentry->d_sb;
 
121
        exist = !!dentry->d_inode;
 
122
        h_dentry = au_h_dptr(dentry, bindex);
 
123
        h_inode = h_dentry->d_inode;
 
124
        if (exist) {
 
125
                err = -ENOENT;
 
126
                if (unlikely(!h_inode || !h_inode->i_nlink))
 
127
                        goto out;
 
128
 
 
129
                h_mode = h_inode->i_mode;
 
130
                if (!isdir) {
 
131
                        err = -EISDIR;
 
132
                        if (unlikely(S_ISDIR(h_mode)))
 
133
                                goto out;
 
134
                } else if (unlikely(!S_ISDIR(h_mode))) {
 
135
                        err = -ENOTDIR;
 
136
                        goto out;
 
137
                }
 
138
        } else {
 
139
                /* rename(2) case */
 
140
                err = -EIO;
 
141
                if (unlikely(h_inode))
 
142
                        goto out;
 
143
        }
 
144
 
 
145
        err = -ENOENT;
 
146
        /* expected parent dir is locked */
 
147
        if (unlikely(h_parent != h_dentry->d_parent))
 
148
                goto out;
 
149
        err = 0;
 
150
 
 
151
        /*
 
152
         * some filesystem may unlink a dir and corrupt its consistency.
 
153
         * so let's try heavy test.
 
154
         */
 
155
        if (1 /*unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY))*/) {
 
156
                struct dentry *h_latest;
 
157
                struct qstr *qstr = &dentry->d_name;
 
158
 
 
159
                err = -EACCES;
 
160
                if (unlikely(au_test_h_perm(h_parent->d_inode,
 
161
                                            MAY_EXEC | MAY_WRITE,
 
162
                                            au_ftest_ndx(ndx->flags, DLGT))))
 
163
                        goto out;
 
164
 
 
165
                h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
 
166
                                           ndx);
 
167
                //err = PTR_ERR(h_latest);
 
168
                err = -EIO;
 
169
                if (IS_ERR(h_latest))
 
170
                        goto out;
 
171
                dput(h_latest);
 
172
                if (h_latest == h_dentry)
 
173
                        err = 0;
 
174
        }
 
175
 
 
176
 out:
 
177
        AuTraceErr(err);
 
178
        return err;
 
179
}
 
180
 
 
181
static struct dentry *
 
182
lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
 
183
                    struct au_dtime *dt)
 
184
{
 
185
        struct dentry *wh_dentry;
 
186
        int err, need_wh;
 
187
        struct dentry *h_parent, *parent, *gparent;
 
188
        struct inode *dir, *h_dir, *gdir;
 
189
        struct au_ndx ndx;
 
190
        struct super_block *sb;
 
191
        struct au_hinode *hgdir;
 
192
        aufs_bindex_t bcpup;
 
193
        unsigned int mnt_flags;
 
194
 
 
195
        LKTRTrace("%.*s, isdir %d\n", AuDLNPair(dentry), isdir);
 
196
 
 
197
        need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup, NULL);
 
198
        err = need_wh;
 
199
        //err = -1;
 
200
        wh_dentry = ERR_PTR(err);
 
201
        if (unlikely(err < 0))
 
202
                goto out;
 
203
 
 
204
        //todo: meaningless lock if CONFIG_AUFS_DEBUG is disabled.
 
205
        hgdir = NULL;
 
206
        bcpup = *rbcpup;
 
207
        sb = dentry->d_sb;
 
208
        mnt_flags = au_mntflags(sb);
 
209
        parent = dentry->d_parent; /* dir inode is locked */
 
210
        if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
 
211
                     && !IS_ROOT(parent))) {
 
212
                gparent = dget_parent(parent);
 
213
                gdir = gparent->d_inode;
 
214
                ii_read_lock_parent2(gdir);
 
215
                hgdir = au_hi(gdir, bcpup);
 
216
                ii_read_unlock(gdir);
 
217
                dput(gparent);
 
218
        }
 
219
        dir = parent->d_inode;
 
220
        IMustLock(dir);
 
221
        h_parent = au_h_dptr(parent, bcpup);
 
222
        h_dir = h_parent->d_inode;
 
223
 
 
224
        AuDbgSleep_UdbaRace();
 
225
        au_hdir_lock(h_dir, dir, bcpup);
 
226
        //todo: revalidate the lower dentry?
 
227
 
 
228
        if (!au_opt_test(mnt_flags, UDBA_NONE) && au_dbstart(dentry) == bcpup) {
 
229
                ndx.nfsmnt = au_nfsmnt(sb, bcpup);
 
230
                ndx.flags = 0;
 
231
                if (unlikely(au_opt_test_dlgt(mnt_flags)))
 
232
                        au_fset_ndx(ndx.flags, DLGT);
 
233
                ndx.nd = NULL;
 
234
                //ndx.br = au_sbr(sb, bcpup);
 
235
                //ndx.nd_file = NULL;
 
236
                err = au_may_del(dentry, bcpup, h_parent, isdir, &ndx);
 
237
                wh_dentry = ERR_PTR(err);
 
238
                if (unlikely(err))
 
239
                        goto out_dir;
 
240
        }
 
241
 
 
242
        au_dtime_store(dt, parent, h_parent, hgdir);
 
243
        wh_dentry = NULL;
 
244
        if (!need_wh)
 
245
                goto out; /* success, no need to create whiteout */
 
246
 
 
247
        ndx.nfsmnt = au_nfsmnt(sb, bcpup);
 
248
        ndx.flags = 0;
 
249
        if (unlikely(au_opt_test_dlgt(mnt_flags)))
 
250
                au_fset_ndx(ndx.flags, DLGT);
 
251
        ndx.nd = NULL;
 
252
        //ndx.br = NULL;
 
253
        wh_dentry = au_wh_create(dir, dentry, bcpup, h_parent, &ndx);
 
254
        //wh_dentry = ERR_PTR(-1);
 
255
        if (!IS_ERR(wh_dentry))
 
256
                goto out; /* success */
 
257
        /* returns with the parent is locked and wh_dentry is DGETed */
 
258
 
 
259
 out_dir:
 
260
        au_hdir_unlock(h_dir, dir, bcpup);
 
261
 out:
 
262
        AuTraceErrPtr(wh_dentry);
 
263
        return wh_dentry;
 
264
}
 
265
 
 
266
static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
 
267
                           struct au_nhash *whlist, struct inode *dir)
 
268
{
 
269
        int rmdir_later, err;
 
270
        struct dentry *h_dentry;
 
271
        struct inode *inode, *h_inode;
 
272
        struct super_block *sb;
 
273
 
 
274
        LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
 
275
 
 
276
        inode = NULL;
 
277
        h_inode = NULL;
 
278
        sb = dentry->d_sb;
 
279
        if (unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY))) {
 
280
                inode = dentry->d_inode;
 
281
                h_inode = au_h_iptr(inode, bindex);
 
282
                au_hdir2_lock(h_inode, inode, bindex);
 
283
        }
 
284
        err = au_whtmp_ren(dir, dentry, bindex, /*noself*/1);
 
285
        if (unlikely(inode))
 
286
                au_hdir_unlock(h_inode, inode, bindex);
 
287
        //err = -1;
 
288
        if (unlikely(err))
 
289
                goto out;
 
290
 
 
291
        h_dentry = au_h_dptr(dentry, bindex);
 
292
        if (!au_test_nfs(h_dentry->d_sb)) {
 
293
                const int dirwh = au_sbi(sb)->si_dirwh;
 
294
                rmdir_later = (dirwh <= 1);
 
295
                if (!rmdir_later)
 
296
                        rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
 
297
                                                              dirwh);
 
298
                if (rmdir_later)
 
299
                        return rmdir_later;
 
300
        }
 
301
 
 
302
        err = au_whtmp_rmdir(h_dentry, whlist, bindex, dir, dentry->d_inode,
 
303
                             /*noself*/1);
 
304
        //err = -1;
 
305
        if (unlikely(err)) {
 
306
                AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
 
307
                        AuDLNPair(h_dentry), bindex, err);
 
308
                err = 0;
 
309
        }
 
310
 
 
311
 out:
 
312
        AuTraceErr(err);
 
313
        return err;
 
314
}
 
315
 
 
316
static void epilog(struct inode *dir, struct dentry *dentry,
 
317
                   aufs_bindex_t bindex)
 
318
{
 
319
        //todo: unnecessary?
 
320
        d_drop(dentry);
 
321
        dentry->d_inode->i_ctime = dir->i_ctime;
 
322
 
 
323
        if (atomic_read(&dentry->d_count) == 1) {
 
324
                au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
 
325
                au_update_dbstart(dentry);
 
326
        }
 
327
        if (au_ibstart(dir) == bindex)
 
328
                au_cpup_attr_timesizes(dir);
 
329
        dir->i_version++;
 
330
}
 
331
 
 
332
/* revert flags */
 
333
#define AuRev_DLGT      1
 
334
#define au_ftest_rev(flags, name)       ((flags) & AuRev_##name)
 
335
#define au_fset_rev(flags, name)        { (flags) |= AuRev_##name; }
 
336
#define au_fclr_rev(flags, name)        { (flags) &= ~AuRev_##name; }
 
337
#ifndef CONFIG_AUFS_DLGT
 
338
#undef AuRev_DLGT
 
339
#define AuRev_DLGT      0
 
340
#endif
 
341
 
 
342
static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
 
343
                     aufs_bindex_t bwh, struct au_dtime *dt, unsigned int flags)
 
344
{
 
345
        int rerr;
 
346
        struct inode *dir;
 
347
 
 
348
        dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
 
349
        IMustLock(dir);
 
350
        rerr = au_wh_unlink_dentry(dir, wh_dentry, dentry, dir,
 
351
                                   au_ftest_rev(flags, DLGT));
 
352
        //rerr = -1;
 
353
        if (!rerr) {
 
354
                au_set_dbwh(dentry, bwh);
 
355
                au_dtime_revert(dt);
 
356
                return 0;
 
357
        }
 
358
 
 
359
        AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
 
360
                AuDLNPair(dentry), err, rerr);
 
361
        return -EIO;
 
362
}
 
363
 
 
364
/* ---------------------------------------------------------------------- */
 
365
 
 
366
int aufs_unlink(struct inode *dir, struct dentry *dentry)
 
367
{
 
368
        int err, dlgt;
 
369
        struct inode *inode, *h_dir;
 
370
        struct dentry *parent, *wh_dentry, *h_dentry;
 
371
        struct au_dtime dt;
 
372
        aufs_bindex_t bwh, bindex, bstart;
 
373
        struct super_block *sb;
 
374
        struct vfsub_args vargs;
 
375
 
 
376
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
 
377
        IMustLock(dir);
 
378
        inode = dentry->d_inode;
 
379
        if (unlikely(!inode))
 
380
                return -ENOENT; /* possible? */
 
381
        IMustLock(inode);
 
382
 
 
383
        aufs_read_lock(dentry, AuLock_DW);
 
384
        parent = dentry->d_parent; /* dir inode is locked */
 
385
        di_write_lock_parent(parent);
 
386
 
 
387
        bstart = au_dbstart(dentry);
 
388
        bwh = au_dbwh(dentry);
 
389
        bindex = -1;
 
390
        wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt);
 
391
        //wh_dentry = ERR_PTR(-1);
 
392
        err = PTR_ERR(wh_dentry);
 
393
        if (IS_ERR(wh_dentry))
 
394
                goto out;
 
395
 
 
396
        sb = dir->i_sb;
 
397
        dlgt = !!au_opt_test_dlgt(au_mntflags(sb));
 
398
        AuDebugOn(au_dbstart(dentry) != bstart);
 
399
        h_dentry = au_h_dptr(dentry, bstart);
 
400
        dget(h_dentry);
 
401
 
 
402
        if (bindex == bstart) {
 
403
                vfsub_args_init(&vargs, NULL, dlgt, 0);
 
404
                h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
 
405
                IMustLock(h_dir);
 
406
                err = vfsub_unlink(h_dir, h_dentry, &vargs);
 
407
                //err = -1;
 
408
        } else {
 
409
                /* dir inode is locked */
 
410
                AuDebugOn(!wh_dentry
 
411
                          || wh_dentry->d_parent != au_h_dptr(parent, bindex));
 
412
                h_dir = wh_dentry->d_parent->d_inode;
 
413
                IMustLock(h_dir);
 
414
                err = 0;
 
415
        }
 
416
 
 
417
        if (!err) {
 
418
                drop_nlink(inode);
 
419
#if 0 //todo: update plink
 
420
                if (unlikely(!inode->i_nlink
 
421
                             && au_plink_test(sb, inode)
 
422
                             /* && atomic_read(&inode->i_count) == 2) */)) {
 
423
                        au_debug_on();
 
424
                        DbgInode(inode);
 
425
                        au_debug_off();
 
426
                }
 
427
#endif
 
428
                epilog(dir, dentry, bindex);
 
429
 
 
430
                /* update target timestamps */
 
431
                if (bindex == bstart) {
 
432
                        au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
 
433
                        inode->i_ctime = h_dentry->d_inode->i_ctime;
 
434
                } else
 
435
                        //todo: this timestamp may be reverted later
 
436
                        inode->i_ctime = h_dir->i_ctime;
 
437
                goto out_unlock; /* success */
 
438
        }
 
439
 
 
440
        /* revert */
 
441
        if (wh_dentry) {
 
442
                int rerr;
 
443
                unsigned int rev_flags;
 
444
 
 
445
                rev_flags = 0;
 
446
                if (unlikely(dlgt))
 
447
                        au_fset_rev(rev_flags, DLGT);
 
448
                rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, rev_flags);
 
449
                if (rerr)
 
450
                        err = rerr;
 
451
        }
 
452
 
 
453
 out_unlock:
 
454
        au_hdir_unlock(h_dir, dir, bindex);
 
455
        dput(wh_dentry);
 
456
        dput(h_dentry);
 
457
 out:
 
458
        di_write_unlock(parent);
 
459
        aufs_read_unlock(dentry, AuLock_DW);
 
460
        AuTraceErr(err);
 
461
        return err;
 
462
}
 
463
 
 
464
int aufs_rmdir(struct inode *dir, struct dentry *dentry)
 
465
{
 
466
        int err, rmdir_later;
 
467
        struct inode *inode, *h_dir;
 
468
        struct dentry *parent, *wh_dentry, *h_dentry;
 
469
        struct au_dtime dt;
 
470
        aufs_bindex_t bwh, bindex, bstart;
 
471
        struct au_whtmp_rmdir_args *args;
 
472
        struct au_nhash *whlist;
 
473
        struct super_block *sb;
 
474
        unsigned int mnt_flags;
 
475
 
 
476
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
 
477
        IMustLock(dir);
 
478
        inode = dentry->d_inode;
 
479
        if (unlikely(!inode))
 
480
                return -ENOENT; /* possible? */
 
481
        IMustLock(inode);
 
482
 
 
483
        whlist = au_nhash_new(GFP_TEMPORARY);
 
484
        err = PTR_ERR(whlist);
 
485
        if (IS_ERR(whlist))
 
486
                goto out;
 
487
 
 
488
        err = -ENOMEM;
 
489
        args = kmalloc(sizeof(*args), GFP_TEMPORARY);
 
490
        //args = NULL;
 
491
        if (unlikely(!args))
 
492
                goto out_whlist;
 
493
 
 
494
        aufs_read_lock(dentry, AuLock_DW);
 
495
        parent = dentry->d_parent; /* dir inode is locked */
 
496
        di_write_lock_parent(parent);
 
497
        err = au_test_empty(dentry, whlist);
 
498
        //err = -1;
 
499
        if (unlikely(err))
 
500
                goto out_args;
 
501
 
 
502
        bstart = au_dbstart(dentry);
 
503
        bwh = au_dbwh(dentry);
 
504
        bindex = -1;
 
505
        wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt);
 
506
        //wh_dentry = ERR_PTR(-1);
 
507
        err = PTR_ERR(wh_dentry);
 
508
        if (IS_ERR(wh_dentry))
 
509
                goto out_args;
 
510
 
 
511
        AuDebugOn(au_dbstart(dentry) != bstart);
 
512
        h_dentry = au_h_dptr(dentry, bstart);
 
513
        dget(h_dentry);
 
514
 
 
515
        rmdir_later = 0;
 
516
        if (bindex == bstart) {
 
517
                h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
 
518
                IMustLock(h_dir);
 
519
                err = renwh_and_rmdir(dentry, bstart, whlist, dir);
 
520
                //err = -1;
 
521
                if (err > 0) {
 
522
                        rmdir_later = err;
 
523
                        err = 0;
 
524
                }
 
525
        } else {
 
526
                /* dir inode is locked */
 
527
                AuDebugOn(!wh_dentry
 
528
                          || wh_dentry->d_parent != au_h_dptr(parent, bindex));
 
529
                h_dir = wh_dentry->d_parent->d_inode;
 
530
                IMustLock(h_dir);
 
531
                err = 0;
 
532
        }
 
533
 
 
534
        sb = dentry->d_sb;
 
535
        mnt_flags = au_mntflags(sb);
 
536
        if (!err) {
 
537
                //aufs_bindex_t bi, bend;
 
538
 
 
539
                if (unlikely(au_opt_test(mnt_flags, UDBA_INOTIFY)
 
540
                             && rmdir_later))
 
541
                        au_reset_hinotify(inode, /*flags*/0);
 
542
                clear_nlink(inode);
 
543
                au_set_dbdiropq(dentry, -1);
 
544
                epilog(dir, dentry, bindex);
 
545
 
 
546
                if (rmdir_later) {
 
547
                        au_whtmp_kick_rmdir(h_dentry, whlist, bstart, dir,
 
548
                                            inode, /*noself*/1, args);
 
549
                        args = NULL;
 
550
                }
 
551
 
 
552
                goto out_unlock; /* success */
 
553
        }
 
554
 
 
555
        /* revert */
 
556
        LKTRLabel(revert);
 
557
        if (wh_dentry) {
 
558
                int rerr;
 
559
                unsigned int rev_flags;
 
560
 
 
561
                rev_flags = 0;
 
562
                if (unlikely(au_opt_test_dlgt(mnt_flags)))
 
563
                        au_fset_rev(rev_flags, DLGT);
 
564
                rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, rev_flags);
 
565
                if (rerr)
 
566
                        err = rerr;
 
567
        }
 
568
 
 
569
 out_unlock:
 
570
        au_hdir_unlock(h_dir, dir, bindex);
 
571
        dput(wh_dentry);
 
572
        dput(h_dentry);
 
573
 out_args:
 
574
        di_write_unlock(parent);
 
575
        aufs_read_unlock(dentry, AuLock_DW);
 
576
        kfree(args);
 
577
 out_whlist:
 
578
        au_nhash_del(whlist);
 
579
 out:
 
580
        AuTraceErr(err);
 
581
        return err;
 
582
}