2
* Copyright (C) 2005-2008 Junjiro Okajima
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.
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.
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
20
* whiteout for logical deletion and opaque directory
22
* $Id: whout.c,v 1.3 2008/04/28 03:04:54 sfjro Exp $
26
#include <linux/namei.h>
27
//#include <linux/random.h>
28
//#include <linux/security.h>
31
#define WH_MASK S_IRUGO
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.
36
static struct qstr diropq_name = {
37
.name = AUFS_WH_DIROPQ,
38
.len = sizeof(AUFS_WH_DIROPQ) - 1
42
* generate whiteout name, which is NOT terminated by NULL.
43
* @name: original d_name.name
44
* @len: original d_name.len
46
* returns zero when succeeds, otherwise error.
47
* succeeded value as wh->name should be freed by au_wh_name_free().
49
int au_wh_name_alloc(const char *name, int len, struct qstr *wh)
53
AuDebugOn(!name || !len || !wh);
55
if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
58
wh->len = len + AUFS_WH_PFX_LEN;
59
p = kmalloc(wh->len, GFP_KERNEL);
61
//if (LktrCond) {kfree(p); wh->name = p = NULL;}
63
memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
64
memcpy(p + AUFS_WH_PFX_LEN, name, len);
71
void au_wh_name_free(struct qstr *wh)
73
AuDebugOn(!wh || !wh->name);
75
#ifdef CONFIG_AUFS_DEBUG
80
/* ---------------------------------------------------------------------- */
83
* test if the @wh_name exists under @h_parent.
84
* @try_sio specifies the necessary of super-io.
86
int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
90
struct dentry *wh_dentry;
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));
100
if (ndx && ndx->nd) {
101
flags = ndx->nd->flags;
102
ndx->nd->flags &= ~(LOOKUP_OPEN | LOOKUP_CREATE);
106
wh_dentry = au_lkup_one(wh_name->name, h_parent,
109
wh_dentry = au_sio_lkup_one(wh_name->name, h_parent,
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))
119
if (!wh_dentry->d_inode)
120
goto out_wh; /* success */
123
if (S_ISREG(wh_dentry->d_inode->i_mode))
124
goto out_wh; /* success */
127
AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
128
AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
138
* test if the @h_dentry sets opaque or not.
140
int au_diropq_test(struct dentry *h_dentry, struct au_ndx *ndx)
145
LKTRTrace("dentry %.*s\n", AuDLNPair(h_dentry));
146
h_dir = h_dentry->d_inode;
147
AuDebugOn(!S_ISDIR(h_dir->i_mode));
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);
157
* returns a negative dentry whose name is unique and temporary.
159
struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct qstr *prefix,
163
struct dentry *dentry;
165
char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
166
+ HEX_LEN + 1], *name, *p;
167
static unsigned char cnt;
169
LKTRTrace("hp %.*s, prefix %.*s\n",
170
AuDLNPair(h_parent), prefix->len, prefix->name);
171
AuDebugOn(!h_parent->d_inode);
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))
179
dentry = ERR_PTR(-ENOMEM);
180
name = kmalloc(len + 1, GFP_KERNEL);
181
//if (LktrCond) {kfree(name); name = NULL;}
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);
192
AuDebugOn(name + len + 1 - p <= HEX_LEN);
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)
202
/* AuWarn("could not get random name\n"); */
203
dentry = ERR_PTR(-EEXIST);
204
AuDbg("%.*s\n", len, name);
208
if (unlikely(name != defname))
211
AuTraceErrPtr(dentry);
217
* rename the @dentry of @bindex to the whiteouted temporary name.
219
int au_whtmp_ren(struct inode *dir, struct dentry *dentry, aufs_bindex_t bindex,
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 = {
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;
243
mnt_flags = au_mntflags(sb);
244
dlgt = !!au_opt_test_dlgt(mnt_flags);
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
268
/* ---------------------------------------------------------------------- */
270
static int do_unlink_wh(struct inode *h_dir, struct dentry *wh_dentry,
271
struct inode *dir, int dlgt)
273
struct vfsub_args vargs;
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));
279
* forces superio when the dir has a sticky bit.
280
* this may be a violation of unix fs semantics.
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);
288
int au_wh_unlink_dentry(struct inode *h_dir, struct dentry *wh_dentry,
289
struct dentry *dentry, struct inode *dir, int dlgt)
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));
299
err = do_unlink_wh(h_dir, wh_dentry, dir, dlgt);
300
//if (LktrCond) err = -1; // unavailable
302
au_set_dbwh(dentry, -1);
308
static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
309
struct inode *dir, struct au_ndx *ndx)
313
struct dentry *h_dentry;
315
LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(wh));
316
h_dir = h_parent->d_inode;
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)) {
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));
328
err = PTR_ERR(h_dentry);
334
/* ---------------------------------------------------------------------- */
336
static void clean_wh(struct inode *h_dir, struct dentry *wh)
339
struct vfsub_args vargs;
344
vfsub_args_init(&vargs, NULL, 0, 0);
345
err = vfsub_unlink(h_dir, wh, &vargs);
347
AuWarn("failed unlink %.*s (%d), ignored.\n",
352
static void clean_plink(struct inode *h_dir, struct dentry *plink)
355
struct vfsub_args vargs;
359
if (plink->d_inode) {
360
vfsub_args_init(&vargs, NULL, 0, 0);
361
err = vfsub_rmdir(h_dir, plink, &vargs);
363
AuWarn("failed rmdir %.*s (%d), ignored.\n",
364
AuDLNPair(plink), err);
368
static int test_linkable(struct inode *h_dir)
370
if (h_dir->i_op && h_dir->i_op->link)
375
static int plink_dir(struct inode *h_dir, struct dentry *plink)
380
if (!plink->d_inode) {
382
if (unlikely(au_test_nfs(plink->d_sb)))
384
err = vfsub_mkdir(h_dir, plink, mode, /*dlgt*/0);
385
} else if (S_ISDIR(plink->d_inode->i_mode))
388
AuErr("unknown %.*s exists\n", AuDLNPair(plink));
394
* initialize the whiteout base file/dir for @br.
396
int au_wh_init(struct dentry *h_root, struct au_branch *br,
397
struct vfsmount *nfsmnt, struct super_block *sb)
400
struct dentry *wh, *plink;
402
static struct qstr base_name[] = {
404
.name = AUFS_WH_BASENAME,
405
.len = sizeof(AUFS_WH_BASENAME) - 1
408
.name = AUFS_WH_PLINKDIR,
409
.len = sizeof(AUFS_WH_PLINKDIR) - 1
412
struct au_ndx ndx = {
414
.flags = 0, /* always no dlgt */
418
const int do_plink = au_opt_test(au_mntflags(sb), PLINK);
420
LKTRTrace("nfsmnt %p\n", nfsmnt);
421
BrWhMustWriteLock(br);
423
h_dir = h_root->d_inode;
425
/* doubly whiteouted */
426
wh = au_wh_lkup(h_root, base_name + 0, &ndx);
427
//if (LktrCond) {dput(wh); wh = ERR_PTR(-1);}
431
AuDebugOn(br->br_wh && br->br_wh != wh);
433
plink = au_wh_lkup(h_root, base_name + 1, &ndx);
434
err = PTR_ERR(plink);
437
AuDebugOn(br->br_plink && br->br_plink != plink);
445
switch (br->br_perm) {
451
clean_plink(h_dir, plink);
454
case AuBr_RWNoLinkWH:
457
err = test_linkable(h_dir);
461
err = plink_dir(h_dir, plink);
464
br->br_plink = dget(plink);
466
clean_plink(h_dir, plink);
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
478
err = test_linkable(h_dir);
484
err = au_h_create(h_dir, wh, WH_MASK, /*dlgt*/0,
486
else if (S_ISREG(wh->d_inode->i_mode))
489
AuErr("unknown %.*s/%.*s exists\n",
490
AuDLNPair(h_root), AuDLNPair(wh));
495
err = plink_dir(h_dir, plink);
498
br->br_plink = dget(plink);
500
clean_plink(h_dir, plink);
501
br->br_wh = dget(wh);
516
AuErr("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
520
AuErr("an error(%d) on the writable branch %.*s(%s)\n",
521
err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
525
struct reinit_br_wh {
526
struct super_block *sb;
527
struct au_branch *br;
530
static void reinit_br_wh(void *arg)
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;
540
AuDebugOn(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
544
si_write_lock(a->sb);
545
if (unlikely(!au_br_writable(a->br->br_perm)))
547
bindex = au_br_index(a->sb, a->br->br_id);
548
if (unlikely(bindex < 0))
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);
560
br_wh_write_lock(a->br);
561
err = vfsub_unlink(h_dir, a->br->br_wh, &vargs);
562
//if (LktrCond) err = -1;
566
err = au_wh_init(h_root, a->br, au_do_nfsmnt(a->br->br_mnt),
568
br_wh_write_unlock(a->br);
569
au_hdir_unlock(h_dir, dir, bindex);
573
atomic_dec_return(&a->br->br_wh_running);
575
si_write_unlock(a->sb);
578
AuIOErr("err %d\n", err);
581
static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
584
struct reinit_br_wh *arg;
587
if (atomic_inc_return(&br->br_wh_running) != 1)
591
arg = kmalloc(sizeof(*arg), GFP_TEMPORARY);
594
* dec(wh_running), kfree(arg) and au_br_put()
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);
611
atomic_dec_return(&br->br_wh_running);
615
* create the whiteout @wh.
617
static int link_or_create_wh(struct dentry *wh, struct super_block *sb,
618
aufs_bindex_t bindex, struct inode *dir)
621
struct au_branch *br;
622
struct dentry *h_parent;
625
LKTRTrace("%.*s\n", AuDLNPair(wh));
627
h_parent = wh->d_parent; /* dir inode is locked */
628
h_dir = h_parent->d_inode;
631
dlgt = !!au_opt_test_dlgt(au_mntflags(sb));
632
br = au_sbr(sb, bindex);
635
err = vfsub_link(br->br_wh, h_dir, wh, dlgt);
636
if (!err || err != -EMLINK)
639
/* link count full. re-initialize br_wh. */
640
kick_reinit_br_wh(sb, br);
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));
648
br_wh_read_unlock(br);
653
/* ---------------------------------------------------------------------- */
656
* create or remove the diropq.
658
static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
661
struct dentry *opq_dentry, *h_dentry;
664
struct super_block *sb;
665
struct au_ndx ndx = {
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));
678
/* already checked by au_test_h_perm(). */
680
ndx.nfsmnt = au_nfsmnt(sb, bindex);
682
if (unlikely(au_ftest_diropq(flags, DLGT))) {
684
au_fset_ndx(ndx.flags, DLGT);
686
opq_dentry = au_lkup_one(diropq_name.name, h_dentry, diropq_name.len,
688
//if (LktrCond) {dput(opq_dentry); opq_dentry = ERR_PTR(-1);}
689
if (IS_ERR(opq_dentry))
692
if (au_ftest_diropq(flags, CREATE)) {
693
AuDebugOn(opq_dentry->d_inode);
694
err = link_or_create_wh(opq_dentry, sb, bindex,
696
//if (LktrCond) {vfs_unlink(h_dir, opq_dentry); err = -1;}
698
au_set_dbdiropq(dentry, bindex);
699
goto out; /* success */
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;
707
au_set_dbdiropq(dentry, -1);
710
opq_dentry = ERR_PTR(err);
713
AuTraceErrPtr(opq_dentry);
717
struct do_diropq_args {
718
struct dentry **errp;
719
struct dentry *dentry;
720
aufs_bindex_t bindex;
724
static void call_do_diropq(void *args)
726
struct do_diropq_args *a = args;
727
*a->errp = do_diropq(a->dentry, a->bindex, a->flags);
730
struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
733
struct dentry *diropq, *h_dentry;
735
LKTRTrace("%.*s, bindex %d, flags 0x%x\n",
736
AuDLNPair(dentry), bindex, flags);
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);
744
struct do_diropq_args args = {
750
wkq_err = au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
751
if (unlikely(wkq_err))
752
diropq = ERR_PTR(wkq_err);
755
AuTraceErrPtr(diropq);
759
/* ---------------------------------------------------------------------- */
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.
767
struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
772
struct dentry *wh_dentry;
774
LKTRTrace("%.*s/%.*s\n", AuDLNPair(h_parent), AuLNPair(base_name));
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);
780
/* do not superio. */
781
wh_dentry = au_lkup_one(wh_name.name, h_parent,
783
au_wh_name_free(&wh_name);
785
AuTraceErrPtr(wh_dentry);
790
* link/create a whiteout for @dentry on @bindex.
792
struct dentry *au_wh_create(struct inode *dir, struct dentry *dentry,
793
aufs_bindex_t bindex, struct dentry *h_parent,
796
struct dentry *wh_dentry;
798
struct super_block *sb;
800
LKTRTrace("%.*s/%.*s on b%d\n", AuDLNPair(h_parent),
801
AuDLNPair(dentry), bindex);
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);
810
au_set_dbwh(dentry, bindex);
813
wh_dentry = ERR_PTR(err);
817
AuTraceErrPtr(wh_dentry);
821
/* ---------------------------------------------------------------------- */
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,
832
struct hlist_head *head;
833
struct au_vdir_wh *tpos;
834
struct hlist_node *pos;
835
struct au_vdir_destr *str;
837
LKTRTrace("%.*s\n", AuDLNPair(h_parent));
838
h_dir = h_parent->d_inode;
839
AuDebugOn(IS_RDONLY(h_dir));
840
//SiMustReadLock(??);
845
//if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
846
if (unlikely(!wh_name.name))
848
memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
849
p += AUFS_WH_PFX_LEN;
851
/* already checked by au_test_h_perm(). */
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)
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,
864
//if (LktrCond) err = -1;
869
AuIOErr("whiteout name too long %.*s\n",
870
str->len, str->name);
875
__putname(wh_name.name);
882
struct del_wh_children_args {
884
struct au_nhash *whlist;
885
struct dentry *h_parent;
886
aufs_bindex_t bindex;
891
static void call_del_wh_children(void *args)
893
struct del_wh_children_args *a = args;
894
*a->errp = del_wh_children(a->whlist, a->h_parent, a->bindex,
898
/* ---------------------------------------------------------------------- */
901
* rmdir the whiteouted temporary named dir @h_dentry.
902
* @whlist: whiteouted children.
904
int au_whtmp_rmdir(struct dentry *h_dentry, struct au_nhash *whlist,
905
aufs_bindex_t bindex, struct inode *dir, struct inode *inode,
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 = {
920
LKTRTrace("hd %.*s, b%d, i%lu\n",
921
AuDLNPair(h_dentry), bindex, dir->i_ino);
924
h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
928
mnt_flags = au_mntflags(sb);
929
dlgt = !!au_opt_test_dlgt(mnt_flags);
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);
938
* someone else might change some whiteouts while we were sleeping.
939
* it means this whlist may have an obsoleted entry.
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);
946
unsigned int flags = ndx.flags;
947
struct del_wh_children_args args = {
950
.h_parent = h_dentry,
957
wkq_err = au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
958
if (unlikely(wkq_err))
962
au_hdir_unlock(h_inode, inode, bindex);
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);
971
//if (LktrCond) err = -1;
975
if (au_ibstart(dir) == bindex) {
976
au_cpup_attr_timesizes(dir);
977
//au_cpup_attr_nlink(dir);
980
return 0; /* success */
983
AuWarn("failed removing %.*s(%d), ignored\n", AuDLNPair(h_dentry), err);
987
static void au_whtmp_rmdir_free_args(struct au_whtmp_rmdir_args *args)
989
dput(args->h_dentry);
990
au_nhash_fin(&args->whlist);
992
mutex_unlock(&args->dir->i_mutex);
997
static void do_rmdir_whtmp(void *args)
1000
struct au_whtmp_rmdir_args *a = args;
1001
struct super_block *sb;
1003
LKTRTrace("%.*s, b%d, dir i%lu\n",
1004
AuDLNPair(a->h_dentry), a->bindex, a->dir->i_ino);
1006
mutex_lock(&a->dir->i_mutex);
1009
si_read_lock(sb, !AuLock_FLUSH);
1010
err = au_test_ro(sb, a->bindex, NULL);
1012
struct dentry *h_parent = dget_parent(a->h_dentry);
1013
struct inode *h_dir = h_parent->d_inode;
1015
ii_write_lock_child(a->inode);
1016
ii_write_lock_parent(a->dir);
1017
au_hdir_lock(h_dir, a->dir, a->bindex);
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);
1029
au_whtmp_rmdir_free_args(a);
1031
AuIOErr("err %d\n", err);
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)
1041
LKTRTrace("%.*s\n", AuDLNPair(h_dentry));
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);