~ubuntu-branches/ubuntu/utopic/aufs/utopic

« back to all changes in this revision

Viewing changes to fs/aufs/whout.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2007-06-04 15:17:03 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070604151703-ur9mjtbbpwoga2y6
Tags: 0+20070605-1
* New upstream snapshot
* Remove unionctl

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 */
18
18
 
19
 
/* $Id: whout.c,v 1.13 2007/05/07 03:46:08 sfjro Exp $ */
 
19
/* $Id: whout.c,v 1.17 2007/06/04 02:17:35 sfjro Exp $ */
20
20
 
21
21
#include <linux/fs.h>
22
22
#include <linux/namei.h>
46
46
{
47
47
        char *p;
48
48
 
49
 
        DEBUG_ON(!name || !len || !wh);
 
49
        AuDebugOn(!name || !len || !wh);
50
50
 
51
 
        if (unlikely(len > PATH_MAX - AUFS_WH_LEN))
 
51
        if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
52
52
                return -ENAMETOOLONG;
53
53
 
54
 
        wh->len = len + AUFS_WH_LEN;
 
54
        wh->len = len + AUFS_WH_PFX_LEN;
55
55
        wh->name = p = kmalloc(wh->len, GFP_KERNEL);
56
56
        //if (LktrCond) {kfree(p); wh->name = p = NULL;}
57
57
        if (p) {
58
 
                memcpy(p, AUFS_WH_PFX, AUFS_WH_LEN);
59
 
                memcpy(p + AUFS_WH_LEN, name, len);
 
58
                memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
 
59
                memcpy(p + AUFS_WH_PFX_LEN, name, len);
60
60
                //smp_mb();
61
61
                return 0;
62
62
        }
65
65
 
66
66
void au_free_whname(struct qstr *wh)
67
67
{
68
 
        DEBUG_ON(!wh || !wh->name);
 
68
        AuDebugOn(!wh || !wh->name);
69
69
        kfree(wh->name);
70
70
#ifdef CONFIG_AUFS_DEBUG
71
71
        wh->name = NULL;
88
88
        LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n", DLNPair(hidden_parent),
89
89
                  wh_name->len, wh_name->name, lkup->nfsmnt, lkup->dlgt);
90
90
        hidden_dir = hidden_parent->d_inode;
91
 
        DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
 
91
        AuDebugOn(!S_ISDIR(hidden_dir->i_mode));
92
92
        IMustLock(hidden_dir);
93
93
 
94
94
        if (!try_sio)
131
131
 
132
132
        LKTRTrace("dentry %.*s\n", DLNPair(hidden_dentry));
133
133
        hidden_dir = hidden_dentry->d_inode;
134
 
        DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
 
134
        AuDebugOn(!S_ISDIR(hidden_dir->i_mode));
135
135
        IMustLock(hidden_dir);
136
136
 
137
137
        err = is_wh(hidden_dentry, &diropq_name, /*try_sio*/1, lkup);
148
148
#define HEX_LEN 4
149
149
        struct dentry *dentry;
150
150
        int len, i;
151
 
        char defname[AUFS_WH_LEN * 2 + DNAME_INLINE_LEN_MIN + 1 + HEX_LEN + 1],
152
 
                *name, *p;
 
151
        char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
 
152
                     + HEX_LEN + 1], *name, *p;
153
153
        static unsigned char cnt;
154
154
 
155
155
        LKTRTrace("hp %.*s, prefix %.*s\n",
156
156
                  DLNPair(hidden_parent), prefix->len, prefix->name);
157
 
        DEBUG_ON(!hidden_parent->d_inode);
 
157
        AuDebugOn(!hidden_parent->d_inode);
158
158
        IMustLock(hidden_parent->d_inode);
159
159
 
160
160
        name = defname;
171
171
        }
172
172
 
173
173
        // doubly whiteout-ed
174
 
        memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_LEN * 2);
175
 
        p = name + AUFS_WH_LEN * 2;
 
174
        memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
 
175
        p = name + AUFS_WH_PFX_LEN * 2;
176
176
        memcpy(p, prefix->name, prefix->len);
177
177
        p += prefix->len;
178
178
        *p++ = '.';
179
 
        DEBUG_ON(name + len + 1 - p <= HEX_LEN);
 
179
        AuDebugOn(name + len + 1 - p <= HEX_LEN);
180
180
 
181
181
        for (i = 0; i < 3; i++) {
182
182
                sprintf(p, "%.*d", HEX_LEN, cnt++);
213
213
 
214
214
        LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
215
215
        hidden_dentry = au_h_dptr_i(dentry, bindex);
216
 
        DEBUG_ON(!hidden_dentry || !hidden_dentry->d_inode);
217
 
        hidden_parent = hidden_dentry->d_parent;
 
216
        AuDebugOn(!hidden_dentry || !hidden_dentry->d_inode);
 
217
        hidden_parent = dget_parent(hidden_dentry);
218
218
        hidden_dir = hidden_parent->d_inode;
219
219
        IMustLock(hidden_dir);
220
220
 
232
232
                TraceErr(err);
233
233
                dput(tmp_dentry);
234
234
        }
 
235
        dput(hidden_parent);
235
236
 
236
237
        TraceErr(err);
237
238
        return err;
246
247
 
247
248
        LKTRTrace("hi%lu, wh %.*s, d %p\n", hidden_dir->i_ino,
248
249
                  DLNPair(wh_dentry), dentry);
249
 
        DEBUG_ON((dentry && dbwh(dentry) == -1)
250
 
                 || !wh_dentry->d_inode
251
 
                 || !S_ISREG(wh_dentry->d_inode->i_mode));
 
250
        AuDebugOn((dentry && dbwh(dentry) == -1)
 
251
                  || !wh_dentry->d_inode
 
252
                  || !S_ISREG(wh_dentry->d_inode->i_mode));
252
253
        IMustLock(hidden_dir);
253
254
 
254
255
        err = vfsub_unlink(hidden_dir, wh_dentry, dlgt);
367
368
        err = PTR_ERR(wh);
368
369
        if (IS_ERR(wh))
369
370
                goto out;
370
 
        DEBUG_ON(br->br_wh && br->br_wh != wh);
 
371
        AuDebugOn(br->br_wh && br->br_wh != wh);
371
372
 
372
373
        plink = lkup_wh(h_root, base_name + 1, &lkup);
373
374
        err = PTR_ERR(plink);
374
375
        if (IS_ERR(plink))
375
376
                goto out_dput_wh;
376
 
        DEBUG_ON(br->br_plink && br->br_plink != plink);
 
377
        AuDebugOn(br->br_plink && br->br_plink != plink);
377
378
 
378
379
        dput(br->br_wh);
379
380
        dput(br->br_plink);
472
473
        aufs_bindex_t bindex;
473
474
 
474
475
        TraceEnter();
475
 
        DEBUG_ON(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
 
476
        AuDebugOn(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
476
477
 
477
478
        err = 0;
478
 
        /* big lock */
 
479
        /* aufs big lock */
479
480
        si_write_lock(a->sb);
480
481
        if (unlikely(!br_writable(a->br->br_perm)))
481
482
                goto out;
484
485
                goto out;
485
486
 
486
487
        dir = a->sb->s_root->d_inode;
487
 
        hidden_root = a->br->br_wh->d_parent;
 
488
        hidden_root = dget_parent(a->br->br_wh);
488
489
        hidden_dir = hidden_root->d_inode;
489
 
        DEBUG_ON(!hidden_dir->i_op || !hidden_dir->i_op->link);
 
490
        AuDebugOn(!hidden_dir->i_op || !hidden_dir->i_op->link);
490
491
        hdir_lock(hidden_dir, dir, bindex);
491
492
        br_wh_write_lock(a->br);
492
493
        err = vfsub_unlink(hidden_dir, a->br->br_wh, /*dlgt*/0);
498
499
                              a->sb);
499
500
        br_wh_write_unlock(a->br);
500
501
        hdir_unlock(hidden_dir, dir, bindex);
 
502
        dput(hidden_root);
501
503
 
502
504
 out:
503
505
        atomic_dec(&a->br->br_wh_running);
510
512
 
511
513
static void kick_reinit_br_wh(struct super_block *sb, struct aufs_branch *br)
512
514
{
513
 
        int do_dec;
 
515
        int do_dec, wkq_err;
514
516
        struct reinit_br_wh *arg;
515
517
 
516
518
        do_dec = 1;
524
526
                arg->sb = sb;
525
527
                arg->br = br;
526
528
                br_get(br);
527
 
                au_wkq_nowait(reinit_br_wh, arg, /*dlgt*/0);
 
529
                wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*dlgt*/0);
 
530
                if (unlikely(wkq_err)) {
 
531
                        atomic_dec(&br->br_wh_running);
 
532
                        br_put(br);
 
533
                        kfree(arg);
 
534
                }
528
535
                do_dec = 0;
529
536
        }
530
537
 
546
553
 
547
554
        LKTRTrace("%.*s\n", DLNPair(wh));
548
555
        SiMustReadLock(sb);
549
 
        hidden_parent = wh->d_parent;
 
556
        hidden_parent = dget_parent(wh);
550
557
        hidden_dir = hidden_parent->d_inode;
551
558
        IMustLock(hidden_dir);
552
559
 
567
574
 
568
575
 out:
569
576
        br_wh_read_unlock(br);
 
577
        dput(hidden_parent);
570
578
        TraceErr(err);
571
579
        return err;
572
580
}
588
596
        LKTRTrace("%.*s, bindex %d, do_create %d\n", DLNPair(dentry),
589
597
                  bindex, do_create);
590
598
        hidden_dentry = au_h_dptr_i(dentry, bindex);
591
 
        DEBUG_ON(!hidden_dentry);
 
599
        AuDebugOn(!hidden_dentry);
592
600
        hidden_dir = hidden_dentry->d_inode;
593
 
        DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
 
601
        AuDebugOn(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
594
602
        IMustLock(hidden_dir);
595
603
 
596
604
        // already checked by au_test_perm().
604
612
                goto out;
605
613
 
606
614
        if (do_create) {
607
 
                DEBUG_ON(opq_dentry->d_inode);
 
615
                AuDebugOn(opq_dentry->d_inode);
608
616
                err = link_or_create_wh(opq_dentry, sb, bindex);
609
617
                //if (LktrCond) {vfs_unlink(hidden_dir, opq_dentry); err = -1;}
610
618
                if (!err) {
612
620
                        goto out; /* success */
613
621
                }
614
622
        } else {
615
 
                DEBUG_ON(/* !S_ISDIR(dentry->d_inode->i_mode)
616
 
                          * ||  */!opq_dentry->d_inode);
 
623
                AuDebugOn(/* !S_ISDIR(dentry->d_inode->i_mode)
 
624
                           * ||  */!opq_dentry->d_inode);
617
625
                err = vfsub_unlink(hidden_dir, opq_dentry, lkup.dlgt);
618
626
                //if (LktrCond) err = -1;
619
627
                if (!err)
652
660
        if (!au_test_perm(hidden_dentry->d_inode, MAY_EXEC | MAY_WRITE, dlgt))
653
661
                diropq = do_diropq(dentry, bindex, do_create, dlgt);
654
662
        else {
 
663
                int wkq_err;
655
664
                struct do_diropq_args args = {
656
665
                        .errp           = &diropq,
657
666
                        .dentry         = dentry,
659
668
                        .do_create      = do_create,
660
669
                        .dlgt           = dlgt
661
670
                };
662
 
                au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
 
671
                wkq_err = au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
 
672
                if (unlikely(wkq_err))
 
673
                        diropq = ERR_PTR(wkq_err);
663
674
        }
664
675
 
665
676
        TraceErrPtr(diropq);
749
760
        LKTRTrace("%.*s\n", DLNPair(hidden_parent));
750
761
        hidden_dir = hidden_parent->d_inode;
751
762
        IMustLock(hidden_dir);
752
 
        DEBUG_ON(IS_RDONLY(hidden_dir));
 
763
        AuDebugOn(IS_RDONLY(hidden_dir));
753
764
        //SiMustReadLock(??);
754
765
 
755
766
        err = -ENOMEM;
757
768
        //if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
758
769
        if (unlikely(!wh_name.name))
759
770
                goto out;
760
 
        memcpy(p, AUFS_WH_PFX, AUFS_WH_LEN);
761
 
        p += AUFS_WH_LEN;
 
771
        memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
 
772
        p += AUFS_WH_PFX_LEN;
762
773
 
763
774
        // already checked by au_test_perm().
764
775
        err = 0;
768
779
                        if (tpos->wh_bindex != bindex)
769
780
                                continue;
770
781
                        str = &tpos->wh_str;
771
 
                        if (str->len + AUFS_WH_LEN <= PATH_MAX) {
 
782
                        if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
772
783
                                memcpy(p, str->name, str->len);
773
 
                                wh_name.len = AUFS_WH_LEN + str->len;
 
784
                                wh_name.len = AUFS_WH_PFX_LEN + str->len;
774
785
                                err = unlink_wh_name(hidden_parent, &wh_name,
775
786
                                                     lkup);
776
787
                                //if (LktrCond) err = -1;
817
828
{
818
829
        int err;
819
830
        struct inode *hidden_inode, *hidden_dir;
 
831
        struct dentry *h_parent;
820
832
        struct lkup_args lkup;
821
833
        struct super_block *sb;
822
834
 
824
836
                  DLNPair(hidden_dentry), bindex, dir->i_ino);
825
837
        IMustLock(dir);
826
838
        IiMustAnyLock(dir);
827
 
        hidden_dir = hidden_dentry->d_parent->d_inode;
 
839
        h_parent = dget_parent(hidden_dentry);
 
840
        hidden_dir = h_parent->d_inode;
828
841
        IMustLock(hidden_dir);
829
842
 
830
843
        sb = inode->i_sb;
831
844
        lkup.nfsmnt = au_nfsmnt(sb, bindex);
832
845
        lkup.dlgt = need_dlgt(sb);
833
846
        hidden_inode = hidden_dentry->d_inode;
834
 
        DEBUG_ON(hidden_inode != au_h_iptr_i(inode, bindex));
 
847
        AuDebugOn(hidden_inode != au_h_iptr_i(inode, bindex));
835
848
        hdir2_lock(hidden_inode, inode, bindex);
836
849
        if (!au_test_perm(hidden_inode, MAY_EXEC | MAY_WRITE, lkup.dlgt))
837
850
                err = del_wh_children(whlist, hidden_dentry, bindex, &lkup);
838
851
        else {
 
852
                int wkq_err;
839
853
                // ugly
840
854
                int dlgt = lkup.dlgt;
841
855
                struct del_wh_children_args args = {
847
861
                };
848
862
 
849
863
                lkup.dlgt = 0;
850
 
                au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
 
864
                wkq_err = au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
 
865
                if (unlikely(wkq_err))
 
866
                        err = wkq_err;
851
867
                lkup.dlgt = dlgt;
852
868
        }
853
869
        hdir_unlock(hidden_inode, inode, bindex);
857
873
                //d_drop(hidden_dentry);
858
874
                //if (LktrCond) err = -1;
859
875
        }
 
876
        dput(h_parent);
860
877
 
861
878
        if (!err) {
862
879
                if (ibstart(dir) == bindex) {
872
889
        return err;
873
890
}
874
891
 
875
 
static void do_rmdir_whtmp(void *arg)
 
892
static void rmdir_whtmp_free_args(struct rmdir_whtmp_args *args)
 
893
{
 
894
        dput(args->h_dentry);
 
895
        nhash_fin(&args->whlist);
 
896
        iput(args->inode);
 
897
        i_unlock(args->dir);
 
898
        iput(args->dir);
 
899
        kfree(args);
 
900
}
 
901
 
 
902
static void do_rmdir_whtmp(void *args)
876
903
{
877
904
        int err;
878
 
        struct rmdir_whtmp_arg *a = arg;
 
905
        struct rmdir_whtmp_args *a = args;
879
906
        struct super_block *sb;
880
907
 
881
908
        LKTRTrace("%.*s, b%d, dir i%lu\n",
883
910
 
884
911
        i_lock(a->dir);
885
912
        sb = a->dir->i_sb;
 
913
        //DbgSleep(3);
886
914
        si_read_lock(sb);
887
915
        err = test_ro(sb, a->bindex, NULL);
888
916
        if (!err) {
889
 
                struct inode *hidden_dir = a->h_dentry->d_parent->d_inode;
 
917
                struct dentry *h_parent = dget_parent(a->h_dentry);
 
918
                struct inode *hidden_dir = h_parent->d_inode;
890
919
 
891
920
                ii_write_lock_child(a->inode);
892
921
                ii_write_lock_parent(a->dir);
896
925
                hdir_unlock(hidden_dir, a->dir, a->bindex);
897
926
                ii_write_unlock(a->dir);
898
927
                ii_write_unlock(a->inode);
 
928
                dput(h_parent);
899
929
        }
900
 
        dput(a->h_dentry);
901
 
        nhash_fin(&a->whlist);
902
 
        iput(a->inode);
903
930
        si_read_unlock(sb);
904
 
        i_unlock(a->dir);
905
 
        iput(a->dir);
906
 
        kfree(arg);
 
931
        rmdir_whtmp_free_args(a);
907
932
        if (unlikely(err))
908
933
                IOErr("err %d\n", err);
909
934
}
910
935
 
911
 
void kick_rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
 
936
void kick_rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
912
937
                      aufs_bindex_t bindex, struct inode *dir,
913
 
                      struct inode *inode, struct rmdir_whtmp_arg *arg)
 
938
                      struct inode *inode, struct rmdir_whtmp_args *args)
914
939
{
915
 
        LKTRTrace("%.*s\n", DLNPair(hidden_dentry));
 
940
        int wkq_err;
 
941
 
 
942
        LKTRTrace("%.*s\n", DLNPair(h_dentry));
916
943
        IMustLock(dir);
917
944
 
918
945
        // all post-process will be done in do_rmdir_whtmp().
919
 
        arg->h_dentry = dget(hidden_dentry);
920
 
        nhash_init(&arg->whlist);
921
 
        nhash_move(&arg->whlist, whlist);
922
 
        arg->bindex = bindex;
923
 
        arg->dir = igrab(dir);
924
 
        arg->inode = igrab(inode);
925
 
 
926
 
        au_wkq_nowait(do_rmdir_whtmp, arg, /*dlgt*/0);
 
946
        args->h_dentry = dget(h_dentry);
 
947
        nhash_init(&args->whlist);
 
948
        nhash_move(&args->whlist, whlist);
 
949
        args->bindex = bindex;
 
950
        args->dir = igrab(dir);
 
951
        args->inode = igrab(inode);
 
952
        wkq_err = au_wkq_nowait(do_rmdir_whtmp, args, dir->i_sb, /*dlgt*/0);
 
953
        if (unlikely(wkq_err)) {
 
954
                Warn("rmdir error %.*s (%d), ignored\n",
 
955
                     DLNPair(h_dentry), wkq_err);
 
956
                rmdir_whtmp_free_args(args);
 
957
        }
927
958
}