Revert "UBUNTU: ubuntu: AUFS -- update to b37c575759dc4535ccc03241c584ad5fe69e3b25"
authorAndy Whitcroft <apw@canonical.com>
Sun, 7 Nov 2010 02:06:22 +0000 (02:06 +0000)
committerLeann Ogasawara <leann.ogasawara@canonical.com>
Mon, 28 Mar 2011 13:50:24 +0000 (06:50 -0700)
This reverts commit ed0be8fa661ac39ddea61ed5ee1e892396438769.

Signed-off-by: Andy Whitcroft <apw@canonical.com>

30 files changed:
ubuntu/aufs/BOM
ubuntu/aufs/Makefile
ubuntu/aufs/branch.c
ubuntu/aufs/branch.h
ubuntu/aufs/cpup.c
ubuntu/aufs/debug.c
ubuntu/aufs/dentry.c
ubuntu/aufs/dir.c
ubuntu/aufs/dir.h
ubuntu/aufs/export.c
ubuntu/aufs/f_op.c
ubuntu/aufs/file.c
ubuntu/aufs/file.h
ubuntu/aufs/hnotify.c
ubuntu/aufs/i_op.c
ubuntu/aufs/iinfo.c
ubuntu/aufs/include/linux/aufs_type.h
ubuntu/aufs/inode.c
ubuntu/aufs/ioctl.c
ubuntu/aufs/loop.c
ubuntu/aufs/plink.c
ubuntu/aufs/rdu.c
ubuntu/aufs/sbinfo.c
ubuntu/aufs/super.c
ubuntu/aufs/super.h
ubuntu/aufs/vfsub.c
ubuntu/aufs/vfsub.h
ubuntu/aufs/wkq.c
ubuntu/aufs/wkq.h
ubuntu/aufs/xino.c

index e9825ba..9605587 100644 (file)
@@ -1,2 +1,2 @@
 URL: http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-standalone.git
-COMMIT: b37c575759dc4535ccc03241c584ad5fe69e3b25
+COMMIT: a9be01e5e9688018ebe9ef46ec5414bb356bc556
index b97737d..b9b9a36 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -I$(src)/include
+EXTRA_CFLAGS += -I$(src)/include 
 
 include ${src}/magic.mk
 ifeq (${CONFIG_AUFS_FS},m)
index cd4463c..03725d3 100644 (file)
@@ -54,7 +54,11 @@ static void au_br_do_free(struct au_branch *br)
                else
                        break;
 
+       /* some filesystems acquire extra lock */
+       /* lockdep_off(); */
        mntput(br->br_mnt);
+       /* lockdep_on(); */
+
        kfree(wbr);
        kfree(br);
 }
@@ -522,10 +526,11 @@ int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
  * test if the branch is deletable or not.
  */
 static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
-                           unsigned int sigen, const unsigned int verbose)
+                           unsigned int sigen)
 {
        int err, i, j, ndentry;
        aufs_bindex_t bstart, bend;
+       unsigned char verbose;
        struct au_dcsub_pages dpages;
        struct au_dpage *dpage;
        struct dentry *d;
@@ -538,6 +543,7 @@ static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
        if (unlikely(err))
                goto out_dpages;
 
+       verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
        for (i = 0; !err && i < dpages.ndpage; i++) {
                dpage = dpages.dpages + i;
                ndentry = dpage->ndentry;
@@ -578,13 +584,15 @@ static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
 }
 
 static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
-                          unsigned int sigen, const unsigned int verbose)
+                          unsigned int sigen)
 {
        int err;
        struct inode *i;
        aufs_bindex_t bstart, bend;
+       unsigned char verbose;
 
        err = 0;
+       verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
        list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
                AuDebugOn(!atomic_read(&i->i_count));
                if (!list_empty(&i->i_dentry))
@@ -620,8 +628,7 @@ static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
        return err;
 }
 
-static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
-                             const unsigned int verbose)
+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
 {
        int err;
        unsigned int sigen;
@@ -630,9 +637,9 @@ static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
        DiMustNoWaiters(root);
        IiMustNoWaiters(root->d_inode);
        di_write_unlock(root);
-       err = test_dentry_busy(root, bindex, sigen, verbose);
+       err = test_dentry_busy(root, bindex, sigen);
        if (!err)
-               err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
+               err = test_inode_busy(root->d_sb, bindex, sigen);
        di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
 
        return err;
@@ -769,7 +776,7 @@ int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
                }
        }
 
-       err = test_children_busy(sb->s_root, bindex, verbose);
+       err = test_children_busy(sb->s_root, bindex);
        if (unlikely(err)) {
                if (do_wh)
                        goto out_wh;
index 9e77476..b4a8c2e 100644 (file)
@@ -157,7 +157,8 @@ ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
 struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
 struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
 ino_t au_xino_new_ino(struct super_block *sb);
-void au_xino_delete_inode(struct inode *inode, const int unlinked);
+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+                  ino_t ino);
 int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
                  ino_t ino);
 int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
index 5038e05..25ec28d 100644 (file)
@@ -409,31 +409,29 @@ static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
 {
        int err, symlen;
        mm_segment_t old_fs;
-       union {
-               char *k;
-               char __user *u;
-       } sym;
+       char *sym;
 
        err = -ENOSYS;
        if (unlikely(!h_src->d_inode->i_op->readlink))
                goto out;
 
        err = -ENOMEM;
-       sym.k = __getname_gfp(GFP_NOFS);
-       if (unlikely(!sym.k))
+       sym = __getname_gfp(GFP_NOFS);
+       if (unlikely(!sym))
                goto out;
 
        old_fs = get_fs();
        set_fs(KERNEL_DS);
-       symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
+       symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
+                                               PATH_MAX);
        err = symlen;
        set_fs(old_fs);
 
        if (symlen > 0) {
-               sym.k[symlen] = 0;
-               err = vfsub_symlink(h_dir, h_path, sym.k);
+               sym[symlen] = 0;
+               err = vfsub_symlink(h_dir, h_path, sym);
        }
-       __putname(sym.k);
+       __putname(sym);
 
  out:
        return err;
index 027f28a..abe286a 100644 (file)
@@ -96,15 +96,14 @@ static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
        }
 
        dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
-            " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
+            " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
             bindex,
             inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
             atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
             i_size_read(inode), (unsigned long long)inode->i_blocks,
             (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
             inode->i_mapping ? inode->i_mapping->nrpages : 0,
-            inode->i_state, inode->i_flags, inode->i_version,
-            inode->i_generation,
+            inode->i_state, inode->i_flags, inode->i_generation,
             l ? ", wh " : "", l, n);
        return 0;
 }
@@ -193,9 +192,9 @@ static int do_pri_file(aufs_bindex_t bindex, struct file *file)
            && au_fi(file))
                snprintf(a, sizeof(a), ", mmapped %d",
                         !!au_fi(file)->fi_hvmop);
-       dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
+       dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
             bindex, file->f_mode, file->f_flags, (long)file_count(file),
-            file->f_version, file->f_pos, a);
+            file->f_pos, a);
        if (file->f_dentry)
                do_pri_dentry(bindex, file->f_dentry);
        return 0;
index 1cba7a9..632320f 100644 (file)
@@ -33,7 +33,7 @@ static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
                 * due to whiteout and branch permission.
                 */
                h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
-                                | LOOKUP_FOLLOW | LOOKUP_EXCL);
+                                | LOOKUP_FOLLOW);
                /* unnecessary? */
                h_nd->intent.open.file = NULL;
        } else
index c7fff4b..0c0b275 100644 (file)
@@ -259,6 +259,7 @@ static int aufs_flush_dir(struct file *file, fl_owner_t id)
 
 /* ---------------------------------------------------------------------- */
 
+#if 0
 static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
 {
        int err;
@@ -292,7 +293,8 @@ static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
                err = filemap_fdatawrite(h_inode->i_mapping);
                AuDebugOn(!h_inode->i_fop);
                if (!err && h_inode->i_fop->fsync)
-                       err = h_inode->i_fop->fsync(NULL, datasync);
+                       err = h_inode->i_fop->fsync(NULL, h_path.dentry,
+                                                   datasync);
                if (!err)
                        err = filemap_fdatawrite(h_inode->i_mapping);
                if (!err)
@@ -302,6 +304,7 @@ static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
 
        return err;
 }
+#endif
 
 static int au_do_fsync_dir(struct file *file, int datasync)
 {
@@ -344,10 +347,15 @@ static int au_do_fsync_dir(struct file *file, int datasync)
 static int aufs_fsync_dir(struct file *file, int datasync)
 {
        int err;
-       struct dentry *dentry;
        struct super_block *sb;
+       struct dentry *dentry;
 
+       if (!file) {
+               WARN_ON(1);
+               return -ENOTSUPP;
+       }
        dentry = file->f_dentry;
+
        IMustLock(dentry->d_inode);
 
        err = 0;
@@ -355,10 +363,12 @@ static int aufs_fsync_dir(struct file *file, int datasync)
        si_noflush_read_lock(sb);
        if (file)
                err = au_do_fsync_dir(file, datasync);
+/*
        else {
                di_write_lock_child(dentry);
                err = au_do_fsync_dir_no_file(dentry, datasync);
        }
+*/
        au_cpup_attr_timesizes(dentry->d_inode);
        di_write_unlock(dentry);
        if (file)
@@ -404,7 +414,9 @@ static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
 
                di_read_unlock(dentry, AuLock_IR);
                si_read_unlock(sb);
+               /* lockdep_off(); */
                err = au_vdir_fill_de(file, dirent, filldir);
+               /* lockdep_on(); */
                fsstack_copy_attr_atime(inode, h_inode);
                fi_write_unlock(file);
 
@@ -628,9 +640,6 @@ const struct file_operations aufs_dir_fop = {
        .read           = generic_read_dir,
        .readdir        = aufs_readdir,
        .unlocked_ioctl = aufs_ioctl_dir,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = aufs_compat_ioctl_dir,
-#endif
        .open           = aufs_open_dir,
        .release        = aufs_release_dir,
        .flush          = aufs_flush_dir,
index d070868..a28c69e 100644 (file)
@@ -115,23 +115,12 @@ long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
 #ifdef CONFIG_AUFS_RDU
 /* rdu.c */
 long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-#ifdef CONFIG_COMPAT
-long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
-                        unsigned long arg);
-#endif
 #else
 static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
                                unsigned long arg)
 {
        return -EINVAL;
 }
-#ifdef CONFIG_COMPAT
-static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
-                                      unsigned long arg)
-{
-       return -EINVAL;
-}
-#endif
 #endif
 
 #endif /* __KERNEL__ */
index 82b7b08..b504e08 100644 (file)
@@ -91,28 +91,41 @@ static int au_test_anon(struct dentry *dentry)
 /* ---------------------------------------------------------------------- */
 /* inode generation external table */
 
-void au_xigen_inc(struct inode *inode)
+int au_xigen_inc(struct inode *inode)
 {
+       int err;
        loff_t pos;
        ssize_t sz;
        __u32 igen;
        struct super_block *sb;
        struct au_sbinfo *sbinfo;
 
+       err = 0;
        sb = inode->i_sb;
-       AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
-
        sbinfo = au_sbi(sb);
+       /*
+        * temporary workaround for escaping from SiMustAnyLock() in
+        * au_mntflags(), since this function is called from au_iinfo_fin().
+        */
+       if (unlikely(!au_opt_test(sbinfo->si_mntflags, XINO)))
+               goto out;
+
        pos = inode->i_ino;
        pos *= sizeof(igen);
        igen = inode->i_generation + 1;
        sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
                         sizeof(igen), &pos);
        if (sz == sizeof(igen))
-               return; /* success */
+               goto out; /* success */
 
-       if (unlikely(sz >= 0))
+       err = sz;
+       if (unlikely(sz >= 0)) {
+               err = -EIO;
                AuIOErr("xigen error (%zd)\n", sz);
+       }
+
+ out:
+       return err;
 }
 
 int au_xigen_new(struct inode *inode)
index 4f3e890..81ccb83 100644 (file)
@@ -621,7 +621,7 @@ static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
                .errp           = &err
        };
 
-       wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
+       wkq_err = au_wkq_wait(au_call_mmap_pre, &args);
        if (unlikely(wkq_err))
                err = wkq_err;
        if (unlikely(err))
@@ -686,12 +686,11 @@ static int aufs_fsync_nondir(struct file *file, int datasync)
 {
        int err;
        struct au_pin pin;
-       struct dentry *dentry;
        struct inode *inode;
        struct file *h_file;
        struct super_block *sb;
+       struct dentry *dentry = file->f_dentry;
 
-       dentry = file->f_dentry;
        inode = dentry->d_inode;
        IMustLock(file->f_mapping->host);
        if (inode != file->f_mapping->host) {
@@ -719,13 +718,15 @@ static int aufs_fsync_nondir(struct file *file, int datasync)
        err = -EINVAL;
        h_file = au_hf_top(file);
        if (h_file->f_op && h_file->f_op->fsync) {
+               struct dentry *h_d;
                struct mutex *h_mtx;
 
                /*
                 * no filemap_fdatawrite() since aufs file has no its own
                 * mapping, but dir.
                 */
-               h_mtx = &h_file->f_dentry->d_inode->i_mutex;
+               h_d = h_file->f_dentry;
+               h_mtx = &h_d->d_inode->i_mutex;
                mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
                err = h_file->f_op->fsync(h_file, datasync);
                if (!err)
@@ -866,9 +867,6 @@ const struct file_operations aufs_file_fop = {
        .poll           = aufs_poll,
 #endif
        .unlocked_ioctl = aufs_ioctl_nondir,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = aufs_ioctl_nondir, /* same */
-#endif
        .mmap           = aufs_mmap,
        .open           = aufs_open_nondir,
        .flush          = aufs_flush_nondir,
index 45bdca7..8e7b5f0 100644 (file)
@@ -318,12 +318,12 @@ int au_do_flush(struct file *file, fl_owner_t id,
        inode = dentry->d_inode;
        si_noflush_read_lock(sb);
        fi_read_lock(file);
-       ii_read_lock_child(inode);
+       di_read_lock_child(dentry, AuLock_IW);
 
        err = flush(file, id);
        au_cpup_attr_timesizes(inode);
 
-       ii_read_unlock(inode);
+       di_read_unlock(dentry, AuLock_IW);
        fi_read_unlock(file);
        si_read_unlock(sb);
        return err;
index b871cdd..b2854ac 100644 (file)
@@ -140,10 +140,6 @@ int au_finfo_init(struct file *file, struct au_fidir *fidir);
 
 /* ioctl.c */
 long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
-#ifdef CONFIG_COMPAT
-long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
-                          unsigned long arg);
-#endif
 
 /* ---------------------------------------------------------------------- */
 
index d2bdb55..f03df3b 100644 (file)
@@ -598,7 +598,13 @@ int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
 
        err = -ENOMEM;
        /* iput() and kfree() will be called in au_hnotify() */
+       /*
+        * inotify_mutex is already acquired and kmalloc/prune_icache may lock
+        * iprune_mutex. strange.
+        */
+       /* lockdep_off(); */
        args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
+       /* lockdep_on(); */
        if (unlikely(!args)) {
                AuErr1("no memory\n");
                iput(dir);
@@ -620,7 +626,9 @@ int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
                p[len] = 0;
        }
 
+       /* lockdep_off(); */
        err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
+       /* lockdep_on(); */
        if (unlikely(err)) {
                pr_err("wkq %d\n", err);
                iput(args->h_child_inode);
index e9f0306..1ca1919 100644 (file)
@@ -152,9 +152,11 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
                                  struct nameidata *nd)
 {
        struct dentry *ret, *parent;
-       struct inode *inode;
+       struct inode *inode, *h_inode;
+       struct mutex *mtx;
        struct super_block *sb;
        int err, npositive;
+       aufs_bindex_t bstart;
 
        IMustLock(dir);
 
@@ -179,7 +181,19 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
 
        inode = NULL;
        if (npositive) {
-               inode = au_new_inode(dentry, /*must_new*/0);
+               bstart = au_dbstart(dentry);
+               h_inode = au_h_dptr(dentry, bstart)->d_inode;
+               if (!S_ISDIR(h_inode->i_mode)) {
+                       /*
+                        * stop 'race'-ing between hardlinks under different
+                        * parents.
+                        */
+                       mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
+                       mutex_lock(mtx);
+                       inode = au_new_inode(dentry, /*must_new*/0);
+                       mutex_unlock(mtx);
+               } else
+                       inode = au_new_inode(dentry, /*must_new*/0);
                ret = (void *)inode;
        }
        if (IS_ERR(inode))
@@ -659,7 +673,7 @@ static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
 
                if (ia->ia_size < i_size_read(inode)) {
                        /* unmap only */
-                       err = simple_setsize(inode, ia->ia_size);
+                       err = vmtruncate(inode, ia->ia_size);
                        if (unlikely(err))
                                goto out_unlock;
                }
@@ -830,31 +844,29 @@ static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
 static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        int err;
+       char *buf;
        mm_segment_t old_fs;
-       union {
-               char *k;
-               char __user *u;
-       } buf;
 
        err = -ENOMEM;
-       buf.k = __getname_gfp(GFP_NOFS);
-       if (unlikely(!buf.k))
+       buf = __getname_gfp(GFP_NOFS);
+       if (unlikely(!buf))
                goto out;
 
        aufs_read_lock(dentry, AuLock_IR);
        old_fs = get_fs();
        set_fs(KERNEL_DS);
-       err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
+       err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
+                        PATH_MAX);
        set_fs(old_fs);
        aufs_read_unlock(dentry, AuLock_IR);
 
        if (err >= 0) {
-               buf.k[err] = 0;
+               buf[err] = 0;
                /* will be freed by put_link */
-               nd_set_link(nd, buf.k);
+               nd_set_link(nd, buf);
                return NULL; /* success */
        }
-       __putname(buf.k);
+       __putname(buf);
 
  out:
        path_put(&nd->path);
index d5fbc87..eaab557 100644 (file)
@@ -211,47 +211,67 @@ int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
        return err;
 }
 
+static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
+                          ino_t ino)
+{
+       int err;
+       aufs_bindex_t bindex;
+       unsigned char locked;
+
+       err = 0;
+       locked = !!si_noflush_read_trylock(sb);
+       bindex = au_br_index(sb, hinode->hi_id);
+       if (bindex >= 0)
+               err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
+       /* error action? */
+       if (locked)
+               si_read_unlock(sb);
+       return err;
+}
+
 void au_iinfo_fin(struct inode *inode)
 {
+       ino_t ino;
+       aufs_bindex_t bend;
+       unsigned char unlinked = !inode->i_nlink;
        struct au_iinfo *iinfo;
        struct au_hinode *hi;
        struct super_block *sb;
-       aufs_bindex_t bindex, bend;
-       const unsigned char unlinked = !inode->i_nlink;
+
+       if (unlinked) {
+               int err = au_xigen_inc(inode);
+               if (unlikely(err))
+                       AuWarn1("failed resetting i_generation, %d\n", err);
+       }
 
        iinfo = au_ii(inode);
        /* bad_inode case */
        if (!iinfo)
                return;
 
-       sb = inode->i_sb;
-       if (si_pid_test(sb))
-               au_xino_delete_inode(inode, unlinked);
-       else {
-               /*
-                * it is safe to hide the dependency between sbinfo and
-                * sb->s_umount.
-                */
-               lockdep_off();
-               si_noflush_read_lock(sb);
-               au_xino_delete_inode(inode, unlinked);
-               si_read_unlock(sb);
-               lockdep_on();
-       }
-
        if (iinfo->ii_vdir)
                au_vdir_free(iinfo->ii_vdir);
 
-       bindex = iinfo->ii_bstart;
-       if (bindex >= 0) {
-               hi = iinfo->ii_hinode + bindex;
+       if (iinfo->ii_bstart >= 0) {
+               sb = inode->i_sb;
+               ino = 0;
+               if (unlinked)
+                       ino = inode->i_ino;
+               hi = iinfo->ii_hinode + iinfo->ii_bstart;
                bend = iinfo->ii_bend;
-               while (bindex++ <= bend) {
-                       if (hi->hi_inode)
+               while (iinfo->ii_bstart++ <= bend) {
+                       if (hi->hi_inode) {
+                               if (unlinked || !hi->hi_inode->i_nlink) {
+                                       au_iinfo_write0(sb, hi, ino);
+                                       /* ignore this error */
+                                       ino = 0;
+                               }
                                au_hiput(hi);
+                       }
                        hi++;
                }
        }
+
        kfree(iinfo->ii_hinode);
        AuRwDestroy(&iinfo->ii_rwsem);
 }
index 5b6dc2d..35b39e0 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/limits.h>
 #include <linux/types.h>
 
-#define AUFS_VERSION   "2-standalone.tree-35-rcN-20100705"
+#define AUFS_VERSION   "2-standalone.tree-35-rcN-20100531"
 
 /* todo? move this to linux-2.6.19/include/magic.h */
 #define AUFS_SUPER_MAGIC       ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -79,7 +79,6 @@ typedef __s16 aufs_bindex_t;
 #define AUFS_RDBLK_DEF         512 /* bytes */
 #define AUFS_RDHASH_DEF                32
 #define AUFS_WKQ_NAME          AUFS_NAME "d"
-#define AUFS_WKQ_PRE_NAME      AUFS_WKQ_NAME "_pre"
 #define AUFS_MFS_SECOND_DEF    30 /* seconds */
 #define AUFS_PLINK_WARN                100 /* number of plinks */
 
@@ -158,11 +157,12 @@ static inline int au_rdu_len(int nlen)
 
 union au_rdu_ent_ul {
        struct au_rdu_ent __user        *e;
-       __u64                           ul;
+       unsigned long                   ul;
 };
 
 enum {
        AufsCtlRduV_SZ,
+       AufsCtlRduV_SZ_PTR,
        AufsCtlRduV_End
 };
 
index 0da679d..ab60654 100644 (file)
@@ -271,10 +271,11 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
 {
        int err;
        struct mutex *mtx;
+       const int isdir = (d_type == DT_DIR);
 
-       /* prevent hardlinked inode number from race condition */
+       /* prevent hardlinks from race condition */
        mtx = NULL;
-       if (d_type != DT_DIR) {
+       if (!isdir) {
                mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
                mutex_lock(mtx);
        }
@@ -293,7 +294,7 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
        }
 
  out:
-       if (mtx)
+       if (!isdir)
                mutex_unlock(mtx);
        return err;
 }
@@ -302,10 +303,9 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
 /* todo: return with unlocked? */
 struct inode *au_new_inode(struct dentry *dentry, int must_new)
 {
-       struct inode *inode, *h_inode;
+       struct inode *inode;
        struct dentry *h_dentry;
        struct super_block *sb;
-       struct mutex *mtx;
        ino_t h_ino, ino;
        int err, match;
        aufs_bindex_t bstart;
@@ -313,25 +313,12 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new)
        sb = dentry->d_sb;
        bstart = au_dbstart(dentry);
        h_dentry = au_h_dptr(dentry, bstart);
-       h_inode = h_dentry->d_inode;
-       h_ino = h_inode->i_ino;
-
-       /*
-        * stop 'race'-ing between hardlinks under different
-        * parents.
-        */
-       mtx = NULL;
-       if (!S_ISDIR(h_inode->i_mode))
-               mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
-
- new_ino:
-       if (mtx)
-               mutex_lock(mtx);
+       h_ino = h_dentry->d_inode->i_ino;
        err = au_xino_read(sb, bstart, h_ino, &ino);
        inode = ERR_PTR(err);
        if (unlikely(err))
                goto out;
-
+ new_ino:
        if (!ino) {
                ino = au_xino_new_ino(sb);
                if (unlikely(!ino)) {
@@ -359,21 +346,11 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new)
                iget_failed(inode);
                goto out_err;
        } else if (!must_new) {
-               /*
-                * horrible race condition between lookup, readdir and copyup
-                * (or something).
-                */
-               if (mtx)
-                       mutex_unlock(mtx);
                err = reval_inode(inode, dentry, &match);
-               if (!err) {
-                       mtx = NULL;
+               if (!err)
                        goto out; /* success */
-               } else if (match) {
-                       mtx = NULL;
+               else if (match)
                        goto out_iput;
-               } else if (mtx)
-                       mutex_lock(mtx);
        }
 
        if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
@@ -385,8 +362,6 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new)
        err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
        if (!err) {
                iput(inode);
-               if (mtx)
-                       mutex_unlock(mtx);
                goto new_ino;
        }
 
@@ -395,8 +370,6 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new)
  out_err:
        inode = ERR_PTR(err);
  out:
-       if (mtx)
-               mutex_unlock(mtx);
        return inode;
 }
 
index 331d9eb..a87b578 100644 (file)
@@ -124,32 +124,3 @@ long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
        AuTraceErr(err);
        return err;
 }
-
-#ifdef CONFIG_COMPAT
-long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
-                          unsigned long arg)
-{
-       long err;
-
-       switch (cmd) {
-       case AUFS_CTL_RDU:
-       case AUFS_CTL_RDU_INO:
-               err = au_rdu_compat_ioctl(file, cmd, arg);
-               break;
-
-       default:
-               err = aufs_ioctl_dir(file, cmd, arg);
-       }
-
-       AuTraceErr(err);
-       return err;
-}
-
-#if 0 /* unused yet */
-long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
-                             unsigned long arg)
-{
-       return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
-}
-#endif
-#endif
index c3f2564..506193f 100644 (file)
@@ -47,14 +47,9 @@ int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
 /* true if a kernel thread named 'loop[0-9].*' accesses a file */
 int au_test_loopback_kthread(void)
 {
-       int ret;
+       const char c = current->comm[4];
 
-       ret = 0;
-       if (current->flags & PF_KTHREAD) {
-               const char c = current->comm[4];
-               ret = ('0' <= c && c <= '9'
-                      && !strncmp(current->comm, "loop", 4));
-       }
-
-       return ret;
+       return current->mm == NULL
+              && '0' <= c && c <= '9'
+              && strncmp(current->comm, "loop", 4) == 0;
 }
index c988bcd..a5a9bec 100644 (file)
@@ -421,6 +421,7 @@ long au_plink_ioctl(struct file *file, unsigned int cmd)
 {
        long err;
        struct super_block *sb;
+       struct au_sbinfo *sbinfo;
 
        err = -EACCES;
        if (!capable(CAP_SYS_ADMIN))
@@ -428,6 +429,7 @@ long au_plink_ioctl(struct file *file, unsigned int cmd)
 
        err = 0;
        sb = file->f_dentry->d_sb;
+       sbinfo = au_sbi(sb);
        switch (cmd) {
        case AUFS_CTL_PLINK_MAINT:
                /*
@@ -438,7 +440,7 @@ long au_plink_ioctl(struct file *file, unsigned int cmd)
                break;
        case AUFS_CTL_PLINK_CLEAN:
                aufs_write_lock(sb->s_root);
-               if (au_opt_test(au_mntflags(sb), PLINK))
+               if (au_opt_test(sbinfo->si_mntflags, PLINK))
                        au_plink_put(sb);
                aufs_write_unlock(sb->s_root);
                break;
index 8784508..b8a2b37 100644 (file)
@@ -20,7 +20,6 @@
  * readdir in userspace.
  */
 
-#include <linux/compat.h>
 #include <linux/fs_stack.h>
 #include <linux/security.h>
 #include <linux/uaccess.h>
@@ -270,19 +269,21 @@ static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
 
 static int au_rdu_verify(struct aufs_rdu *rdu)
 {
-       AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
+       AuDbg("rdu{%llu, %p, (%u, %u) | %u | %llu, %u, %u | "
              "%llu, b%d, 0x%x, g%u}\n",
-             rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
+             rdu->sz, rdu->ent.e, rdu->verify[0], rdu->verify[1],
              rdu->blk,
              rdu->rent, rdu->shwh, rdu->full,
              rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
              rdu->cookie.generation);
 
-       if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
+       if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)
+           && rdu->verify[AufsCtlRduV_SZ_PTR] == sizeof(rdu))
                return 0;
 
-       AuDbg("%u:%u\n",
-             rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
+       AuDbg("%u:%u, %u:%u\n",
+             rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu),
+             rdu->verify[AufsCtlRduV_SZ_PTR], (unsigned int)sizeof(rdu));
        return -EINVAL;
 }
 
@@ -327,51 +328,3 @@ long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        AuTraceErr(err);
        return err;
 }
-
-#ifdef CONFIG_COMPAT
-long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       long err, e;
-       struct aufs_rdu rdu;
-       void __user *p = compat_ptr(arg);
-
-       /* todo: get_user()? */
-       err = copy_from_user(&rdu, p, sizeof(rdu));
-       if (unlikely(err)) {
-               err = -EFAULT;
-               AuTraceErr(err);
-               goto out;
-       }
-       rdu.ent.e = compat_ptr(rdu.ent.ul);
-       err = au_rdu_verify(&rdu);
-       if (unlikely(err))
-               goto out;
-
-       switch (cmd) {
-       case AUFS_CTL_RDU:
-               err = au_rdu(file, &rdu);
-               if (unlikely(err))
-                       break;
-
-               rdu.ent.ul = ptr_to_compat(rdu.ent.e);
-               rdu.tail.ul = ptr_to_compat(rdu.tail.e);
-               e = copy_to_user(p, &rdu, sizeof(rdu));
-               if (unlikely(e)) {
-                       err = -EFAULT;
-                       AuTraceErr(err);
-               }
-               break;
-       case AUFS_CTL_RDU_INO:
-               err = au_rdu_ino(file, &rdu);
-               break;
-
-       default:
-               /* err = -ENOTTY; */
-               err = -EINVAL;
-       }
-
- out:
-       AuTraceErr(err);
-       return err;
-}
-#endif
index c74ca20..89b2b6a 100644 (file)
@@ -29,7 +29,6 @@ void au_si_free(struct kobject *kobj)
 {
        struct au_sbinfo *sbinfo;
        struct super_block *sb;
-       char *locked __maybe_unused; /* debug only */
 
        sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
        AuDebugOn(!list_empty(&sbinfo->si_plink.head));
@@ -39,16 +38,9 @@ void au_si_free(struct kobject *kobj)
        si_write_lock(sb);
        au_xino_clr(sb);
        au_br_free(sbinfo);
-       si_write_unlock(sb);
-
-       AuDebugOn(radix_tree_gang_lookup
-                 (&sbinfo->au_si_pid.tree, (void **)&locked,
-                  /*first_index*/PID_MAX_DEFAULT - 1,
-                  /*max_items*/sizeof(locked)/sizeof(*locked)));
-
        kfree(sbinfo->si_branch);
-       kfree(sbinfo->au_si_pid.bitmap);
        mutex_destroy(&sbinfo->si_xib_mtx);
+       si_write_unlock(sb);
        AuRwDestroy(&sbinfo->si_rwsem);
 
        kfree(sbinfo);
@@ -64,18 +56,10 @@ int au_si_alloc(struct super_block *sb)
        if (unlikely(!sbinfo))
                goto out;
 
-       BUILD_BUG_ON(sizeof(unsigned long) !=
-                    sizeof(*sbinfo->au_si_pid.bitmap));
-       sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
-                                       sizeof(*sbinfo->au_si_pid.bitmap),
-                                       GFP_NOFS);
-       if (unlikely(!sbinfo->au_si_pid.bitmap))
-               goto out_sbinfo;
-
        /* will be reallocated separately */
        sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
        if (unlikely(!sbinfo->si_branch))
-               goto out_pidmap;
+               goto out_sbinfo;
 
        err = sysaufs_si_init(sbinfo);
        if (unlikely(err))
@@ -83,9 +67,6 @@ int au_si_alloc(struct super_block *sb)
 
        au_nwt_init(&sbinfo->si_nowait);
        au_rw_init_wlock(&sbinfo->si_rwsem);
-       spin_lock_init(&sbinfo->au_si_pid.tree_lock);
-       INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
-
        sbinfo->si_bend = -1;
 
        sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
@@ -111,14 +92,11 @@ int au_si_alloc(struct super_block *sb)
        /* leave other members for sysaufs and si_mnt. */
        sbinfo->si_sb = sb;
        sb->s_fs_info = sbinfo;
-       si_pid_set(sb);
        au_debug_sbinfo_init(sbinfo);
        return 0; /* success */
 
  out_br:
        kfree(sbinfo->si_branch);
- out_pidmap:
-       kfree(sbinfo->au_si_pid.bitmap);
  out_sbinfo:
        kfree(sbinfo);
  out:
@@ -222,48 +200,3 @@ void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
        di_write_unlock2(d1, d2);
        si_read_unlock(d1->d_sb);
 }
-
-/* ---------------------------------------------------------------------- */
-
-int si_pid_test_slow(struct super_block *sb)
-{
-       void *p;
-
-       rcu_read_lock();
-       p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
-       rcu_read_unlock();
-
-       return (long)p;
-}
-
-void si_pid_set_slow(struct super_block *sb)
-{
-       int err;
-       struct au_sbinfo *sbinfo;
-
-       AuDebugOn(si_pid_test_slow(sb));
-
-       sbinfo = au_sbi(sb);
-       err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
-       AuDebugOn(err);
-       spin_lock(&sbinfo->au_si_pid.tree_lock);
-       err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
-                               (void *)1);
-       spin_unlock(&sbinfo->au_si_pid.tree_lock);
-       AuDebugOn(err);
-       radix_tree_preload_end();
-}
-
-void si_pid_clr_slow(struct super_block *sb)
-{
-       void *p;
-       struct au_sbinfo *sbinfo;
-
-       AuDebugOn(!si_pid_test_slow(sb));
-
-       sbinfo = au_sbi(sb);
-       spin_lock(&sbinfo->au_si_pid.tree_lock);
-       p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
-       spin_unlock(&sbinfo->au_si_pid.tree_lock);
-       AuDebugOn(1 != (long)p);
-}
index 5c1c823..6a6899b 100644 (file)
@@ -686,7 +686,6 @@ static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
 static const struct super_operations aufs_sop = {
        .alloc_inode    = aufs_alloc_inode,
        .destroy_inode  = aufs_destroy_inode,
-       /* always deleting, no clearing */
        .drop_inode     = generic_delete_inode,
        .show_options   = aufs_show_options,
        .statfs         = aufs_statfs,
index f1d27f5..cd6fdc4 100644 (file)
@@ -61,19 +61,8 @@ struct au_sbinfo {
        /* nowait tasks in the system-wide workqueue */
        struct au_nowait_tasks  si_nowait;
 
-       /*
-        * tried sb->s_umount, but failed due to the dependecy between i_mutex.
-        * rwsem for au_sbinfo is necessary.
-        */
        struct au_rwsem         si_rwsem;
 
-       /* prevent recursive locking in deleting inode */
-       struct {
-               unsigned long           *bitmap;
-               spinlock_t              tree_lock;
-               struct radix_tree_root  tree;
-       } au_si_pid;
-
        /* branch management */
        unsigned int            si_generation;
 
@@ -223,10 +212,6 @@ void aufs_write_unlock(struct dentry *dentry);
 void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
 void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
 
-int si_pid_test_slow(struct super_block *sb);
-void si_pid_set_slow(struct super_block *sb);
-void si_pid_clr_slow(struct super_block *sb);
-
 /* wbr_policy.c */
 extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
 extern struct au_wbr_create_operations au_wbr_create_ops[];
@@ -246,11 +231,10 @@ void au_export_init(struct super_block *sb);
 
 static inline int au_test_nfsd(struct task_struct *tsk)
 {
-       return (current->flags & PF_KTHREAD)
-               && !strcmp(tsk->comm, "nfsd");
+       return !tsk->mm && !strcmp(tsk->comm, "nfsd");
 }
 
-void au_xigen_inc(struct inode *inode);
+int au_xigen_inc(struct inode *inode);
 int au_xigen_new(struct inode *inode);
 int au_xigen_set(struct super_block *sb, struct file *base);
 void au_xigen_clr(struct super_block *sb);
@@ -264,7 +248,7 @@ static inline int au_busy_or_stale(void)
 #else
 AuStubVoid(au_export_init, struct super_block *sb)
 AuStubInt0(au_test_nfsd, struct task_struct *tsk)
-AuStubVoid(au_xigen_inc, struct inode *inode)
+AuStubInt0(au_xigen_inc, struct inode *inode)
 AuStubInt0(au_xigen_new, struct inode *inode)
 AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
 AuStubVoid(au_xigen_clr, struct super_block *sb)
@@ -294,84 +278,19 @@ static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
 
 /* ---------------------------------------------------------------------- */
 
-static inline pid_t si_pid_bit(void)
-{
-       /* the origin of pid is 1, but the bitmap's is 0 */
-       return current->pid - 1;
-}
-
-static inline int si_pid_test(struct super_block *sb)
-{
-       pid_t bit = si_pid_bit();
-       if (bit < PID_MAX_DEFAULT)
-               return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
-       else
-               return si_pid_test_slow(sb);
-}
-
-static inline void si_pid_set(struct super_block *sb)
-{
-       pid_t bit = si_pid_bit();
-       if (bit < PID_MAX_DEFAULT) {
-               AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
-               set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
-               /* smp_mb(); */
-       } else
-               si_pid_set_slow(sb);
-}
-
-static inline void si_pid_clr(struct super_block *sb)
-{
-       pid_t bit = si_pid_bit();
-       if (bit < PID_MAX_DEFAULT) {
-               AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
-               clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
-               /* smp_mb(); */
-       } else
-               si_pid_clr_slow(sb);
-}
-
-/* ---------------------------------------------------------------------- */
-
 /* lock superblock. mainly for entry point functions */
 /*
- * __si_read_lock, __si_write_lock,
- * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
+ * si_noflush_read_lock, si_noflush_write_lock,
+ * si_read_unlock, si_write_unlock, si_downgrade_lock
  */
-AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
+AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
+                      &au_sbi(sb)->si_rwsem);
+AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
 
 #define SiMustNoWaiters(sb)    AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
 #define SiMustAnyLock(sb)      AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
 #define SiMustWriteLock(sb)    AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
 
-static inline void si_noflush_read_lock(struct super_block *sb)
-{
-       __si_read_lock(sb);
-       si_pid_set(sb);
-}
-
-static inline int si_noflush_read_trylock(struct super_block *sb)
-{
-       int locked = __si_read_trylock(sb);
-       if (locked)
-               si_pid_set(sb);
-       return locked;
-}
-
-static inline void si_noflush_write_lock(struct super_block *sb)
-{
-       __si_write_lock(sb);
-       si_pid_set(sb);
-}
-
-static inline int si_noflush_write_trylock(struct super_block *sb)
-{
-       int locked = __si_write_trylock(sb);
-       if (locked)
-               si_pid_set(sb);
-       return locked;
-}
-
 static inline void si_read_lock(struct super_block *sb, int flags)
 {
        if (au_ftest_lock(flags, FLUSH))
@@ -379,46 +298,25 @@ static inline void si_read_lock(struct super_block *sb, int flags)
        si_noflush_read_lock(sb);
 }
 
-static inline int si_read_trylock(struct super_block *sb, int flags)
-{
-       if (au_ftest_lock(flags, FLUSH))
-               au_nwt_flush(&au_sbi(sb)->si_nowait);
-       return si_noflush_read_trylock(sb);
-}
-
-static inline void si_read_unlock(struct super_block *sb)
-{
-       si_pid_clr(sb);
-       __si_read_unlock(sb);
-}
-
 static inline void si_write_lock(struct super_block *sb)
 {
        au_nwt_flush(&au_sbi(sb)->si_nowait);
        si_noflush_write_lock(sb);
 }
 
-#if 0 /* unused */
-static inline int si_write_trylock(struct super_block *sb, int flags)
+static inline int si_read_trylock(struct super_block *sb, int flags)
 {
        if (au_ftest_lock(flags, FLUSH))
                au_nwt_flush(&au_sbi(sb)->si_nowait);
-       return si_noflush_write_trylock(sb);
-}
-#endif
-
-static inline void si_write_unlock(struct super_block *sb)
-{
-       si_pid_clr(sb);
-       __si_write_unlock(sb);
+       return si_noflush_read_trylock(sb);
 }
 
-#if 0 /* unused */
-static inline void si_downgrade_lock(struct super_block *sb)
+static inline int si_write_trylock(struct super_block *sb, int flags)
 {
-       __si_downgrade_lock(sb);
+       if (au_ftest_lock(flags, FLUSH))
+               au_nwt_flush(&au_sbi(sb)->si_nowait);
+       return si_noflush_write_trylock(sb);
 }
-#endif
 
 /* ---------------------------------------------------------------------- */
 
index 29e3390..841bb25 100644 (file)
@@ -100,7 +100,9 @@ struct file *vfsub_filp_open(const char *path, int oflags, int mode)
 {
        struct file *file;
 
+       /* lockdep_off(); */
        file = filp_open(path, oflags, mode);
+       /* lockdep_on(); */
        if (IS_ERR(file))
                goto out;
        vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
@@ -113,7 +115,9 @@ int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
 {
        int err;
 
+       /* lockdep_off(); */
        err = kern_path(name, flags, path);
+       /* lockdep_on(); */
        if (!err && path->dentry->d_inode)
                vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
        return err;
@@ -166,7 +170,9 @@ struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
 {
        struct dentry *d;
 
+       lockdep_off();
        d = lock_rename(d1, d2);
+       lockdep_on();
        au_hn_suspend(hdir1);
        if (hdir1 != hdir2)
                au_hn_suspend(hdir2);
@@ -180,7 +186,9 @@ void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
        au_hn_resume(hdir1);
        if (hdir1 != hdir2)
                au_hn_resume(hdir2);
+       lockdep_off();
        unlock_rename(d1, d2);
+       lockdep_on();
 }
 
 /* ---------------------------------------------------------------------- */
@@ -194,7 +202,7 @@ int vfsub_create(struct inode *dir, struct path *path, int mode)
 
        d = path->dentry;
        path->dentry = d->d_parent;
-       err = security_path_mknod(path, d, mode, 0);
+       err = security_path_mknod(path, path->dentry, mode, 0);
        path->dentry = d;
        if (unlikely(err))
                goto out;
@@ -241,7 +249,7 @@ int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
 
        d = path->dentry;
        path->dentry = d->d_parent;
-       err = security_path_symlink(path, d, symname);
+       err = security_path_symlink(path, path->dentry, symname);
        path->dentry = d;
        if (unlikely(err))
                goto out;
@@ -272,7 +280,7 @@ int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
 
        d = path->dentry;
        path->dentry = d->d_parent;
-       err = security_path_mknod(path, d, mode, dev);
+       err = security_path_mknod(path, path->dentry, mode, dev);
        path->dentry = d;
        if (unlikely(err))
                goto out;
@@ -317,12 +325,14 @@ int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
 
        d = path->dentry;
        path->dentry = d->d_parent;
-       err = security_path_link(src_dentry, path, d);
+       err = security_path_link(src_dentry, path, path->dentry);
        path->dentry = d;
        if (unlikely(err))
                goto out;
 
+       /* lockdep_off(); */
        err = vfs_link(src_dentry, dir, path->dentry);
+       /* lockdep_on(); */
        if (!err) {
                struct path tmp = *path;
                int did;
@@ -357,12 +367,14 @@ int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
        d = path->dentry;
        path->dentry = d->d_parent;
        tmp.dentry = src_dentry->d_parent;
-       err = security_path_rename(&tmp, src_dentry, path, d);
+       err = security_path_rename(&tmp, src_dentry, path, path->dentry);
        path->dentry = d;
        if (unlikely(err))
                goto out;
 
+       /* lockdep_off(); */
        err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
+       /* lockdep_on(); */
        if (!err) {
                int did;
 
@@ -390,7 +402,7 @@ int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
 
        d = path->dentry;
        path->dentry = d->d_parent;
-       err = security_path_mkdir(path, d, mode);
+       err = security_path_mkdir(path, path->dentry, mode);
        path->dentry = d;
        if (unlikely(err))
                goto out;
@@ -421,12 +433,14 @@ int vfsub_rmdir(struct inode *dir, struct path *path)
 
        d = path->dentry;
        path->dentry = d->d_parent;
-       err = security_path_rmdir(path, d);
+       err = security_path_rmdir(path, path->dentry);
        path->dentry = d;
        if (unlikely(err))
                goto out;
 
+       /* lockdep_off(); */
        err = vfs_rmdir(dir, path->dentry);
+       /* lockdep_on(); */
        if (!err) {
                struct path tmp = {
                        .dentry = path->dentry->d_parent,
@@ -459,15 +473,10 @@ ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
 {
        ssize_t err;
        mm_segment_t oldfs;
-       union {
-               void *k;
-               char __user *u;
-       } buf;
 
-       buf.k = kbuf;
        oldfs = get_fs();
        set_fs(KERNEL_DS);
-       err = vfsub_read_u(file, buf.u, count, ppos);
+       err = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
        set_fs(oldfs);
        return err;
 }
@@ -477,7 +486,9 @@ ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
 {
        ssize_t err;
 
+       /* lockdep_off(); */
        err = vfs_write(file, ubuf, count, ppos);
+       /* lockdep_on(); */
        if (err >= 0)
                vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
        return err;
@@ -487,15 +498,10 @@ ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
 {
        ssize_t err;
        mm_segment_t oldfs;
-       union {
-               void *k;
-               const char __user *u;
-       } buf;
 
-       buf.k = kbuf;
        oldfs = get_fs();
        set_fs(KERNEL_DS);
-       err = vfsub_write_u(file, buf.u, count, ppos);
+       err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
        set_fs(oldfs);
        return err;
 }
@@ -518,7 +524,9 @@ int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
 {
        int err;
 
+       /* lockdep_off(); */
        err = vfs_readdir(file, filldir, arg);
+       /* lockdep_on(); */
        if (err >= 0)
                vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
        return err;
@@ -530,7 +538,9 @@ long vfsub_splice_to(struct file *in, loff_t *ppos,
 {
        long err;
 
+       /* lockdep_off(); */
        err = do_splice_to(in, ppos, pipe, len, flags);
+       /* lockdep_on(); */
        file_accessed(in);
        if (err >= 0)
                vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
@@ -542,7 +552,9 @@ long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
 {
        long err;
 
+       /* lockdep_off(); */
        err = do_splice_from(pipe, out, ppos, len, flags);
+       /* lockdep_on(); */
        if (err >= 0)
                vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
        return err;
@@ -574,8 +586,11 @@ int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
        err = locks_verify_truncate(h_inode, h_file, length);
        if (!err)
                err = security_path_truncate(h_path, length, attr);
-       if (!err)
+       if (!err) {
+               /* lockdep_off(); */
                err = do_truncate(h_path->dentry, length, attr, h_file);
+               /* lockdep_on(); */
+       }
 
  out_inode:
        if (!h_file)
@@ -675,7 +690,9 @@ static void call_notify_change(void *args)
 
        *a->errp = -EPERM;
        if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
+               /* lockdep_off(); */
                *a->errp = notify_change(a->path->dentry, a->ia);
+               /* lockdep_on(); */
                if (!*a->errp)
                        vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
        }
@@ -742,7 +759,9 @@ static void call_unlink(void *args)
        if (h_inode)
                atomic_inc(&h_inode->i_count);
 
+       /* lockdep_off(); */
        *a->errp = vfs_unlink(a->dir, d);
+       /* lockdep_on(); */
        if (!*a->errp) {
                struct path tmp = {
                        .dentry = d->d_parent,
index 54553eb..d7e97fc 100644 (file)
@@ -130,7 +130,9 @@ static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
 {
        loff_t err;
 
+       /* lockdep_off(); */
        err = vfs_llseek(file, offset, origin);
+       /* lockdep_on(); */
        return err;
 }
 
index 316e125..a67c31f 100644 (file)
 #include <linux/module.h>
 #include "aufs.h"
 
-/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
-enum {
-       AuWkq_INORMAL,
-       AuWkq_IPRE
-};
-
-static struct {
-       char *name;
-       struct workqueue_struct *wkq;
-} au_wkq[] = {
-       [AuWkq_INORMAL] = {
-               .name = AUFS_WKQ_NAME
-       },
-       [AuWkq_IPRE] = {
-               .name = AUFS_WKQ_PRE_NAME
-       }
-};
+/* internal workqueue named AUFS_WKQ_NAME */
+static struct workqueue_struct *au_wkq;
 
 struct au_wkinfo {
        struct work_struct wk;
@@ -111,36 +96,31 @@ static void au_wkq_comp_free(struct completion *comp __maybe_unused)
 }
 #endif /* 4KSTACKS */
 
-static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
+static void au_wkq_run(struct au_wkinfo *wkinfo, int do_wait)
 {
-       struct workqueue_struct *wkq;
-
        au_dbg_verify_kthread();
-       if (flags & AuWkq_WAIT) {
+       if (do_wait) {
                INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
-               wkq = au_wkq[AuWkq_INORMAL].wkq;
-               if (flags & AuWkq_PRE)
-                       wkq = au_wkq[AuWkq_IPRE].wkq;
-               queue_work(wkq, &wkinfo->wk);
+               queue_work(au_wkq, &wkinfo->wk);
        } else {
                INIT_WORK(&wkinfo->wk, wkq_func);
                schedule_work(&wkinfo->wk);
        }
 }
 
-int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
+int au_wkq_wait(au_wkq_func_t func, void *args)
 {
        int err;
        AuWkqCompDeclare(comp);
        struct au_wkinfo wkinfo = {
-               .flags  = flags,
+               .flags  = AuWkq_WAIT,
                .func   = func,
                .args   = args
        };
 
        err = au_wkq_comp_alloc(&wkinfo, &comp);
        if (!err) {
-               au_wkq_run(&wkinfo, flags);
+               au_wkq_run(&wkinfo, AuWkq_WAIT);
                /* no timeout, no interrupt */
                wait_for_completion(wkinfo.comp);
                au_wkq_comp_free(comp);
@@ -193,29 +173,11 @@ void au_nwt_init(struct au_nowait_tasks *nwt)
 
 void au_wkq_fin(void)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
-               if (au_wkq[i].wkq)
-                       destroy_workqueue(au_wkq[i].wkq);
+       destroy_workqueue(au_wkq);
 }
 
 int __init au_wkq_init(void)
 {
-       int err, i;
-
-       err = 0;
-       for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
-               au_wkq[i].wkq = create_workqueue(au_wkq[i].name);
-               if (IS_ERR(au_wkq[i].wkq))
-                       err = PTR_ERR(au_wkq[i].wkq);
-               else if (!au_wkq[i].wkq)
-                       err = -ENOMEM;
-               if (unlikely(err))
-                       au_wkq[i].wkq = NULL;
-       }
-       if (unlikely(err))
-               au_wkq_fin();
-
-       return err;
+       au_wkq = create_workqueue(AUFS_WKQ_NAME);
+       return 0;
 }
index 4c2a34e..3fe36b3 100644 (file)
@@ -48,13 +48,12 @@ typedef void (*au_wkq_func_t)(void *args);
 
 /* wkq flags */
 #define AuWkq_WAIT     1
-#define AuWkq_PRE      (1 << 1)
 #define au_ftest_wkq(flags, name)      ((flags) & AuWkq_##name)
 #define au_fset_wkq(flags, name)       { (flags) |= AuWkq_##name; }
 #define au_fclr_wkq(flags, name)       { (flags) &= ~AuWkq_##name; }
 
 /* wkq.c */
-int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
+int au_wkq_wait(au_wkq_func_t func, void *args);
 int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
 void au_nwt_init(struct au_nowait_tasks *nwt);
 int __init au_wkq_init(void);
@@ -62,19 +61,9 @@ void au_wkq_fin(void);
 
 /* ---------------------------------------------------------------------- */
 
-static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
-{
-       return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
-}
-
-static inline int au_wkq_wait(au_wkq_func_t func, void *args)
-{
-       return au_wkq_do_wait(AuWkq_WAIT, func, args);
-}
-
 static inline int au_test_wkq(struct task_struct *tsk)
 {
-       return (current->flags & PF_KTHREAD)
+       return !tsk->mm
                && !strncmp(tsk->comm, AUFS_WKQ_NAME "/",
                            sizeof(AUFS_WKQ_NAME));
 }
index 588d1ca..2eba362 100644 (file)
 #include <linux/uaccess.h>
 #include "aufs.h"
 
-ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
                   loff_t *pos)
 {
        ssize_t err;
        mm_segment_t oldfs;
-       union {
-               void *k;
-               char __user *u;
-       } buf;
 
-       buf.k = kbuf;
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        do {
                /* todo: signal_pending? */
-               err = func(file, buf.u, size, pos);
+               err = func(file, (char __user *)buf, size, pos);
        } while (err == -EAGAIN || err == -EINTR);
        set_fs(oldfs);
 
@@ -54,23 +49,20 @@ ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
 
 /* ---------------------------------------------------------------------- */
 
-static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
                              size_t size, loff_t *pos)
 {
        ssize_t err;
        mm_segment_t oldfs;
-       union {
-               void *k;
-               const char __user *u;
-       } buf;
 
-       buf.k = kbuf;
        oldfs = get_fs();
        set_fs(KERNEL_DS);
+       /* lockdep_off(); */
        do {
                /* todo: signal_pending? */
-               err = func(file, buf.u, size, pos);
+               err = func(file, (const char __user *)buf, size, pos);
        } while (err == -EAGAIN || err == -EINTR);
+       /* lockdep_on(); */
        set_fs(oldfs);
 
 #if 0 /* reserved for future use */
@@ -485,83 +477,33 @@ static int xib_pindex(struct super_block *sb, unsigned long pindex)
 
 /* ---------------------------------------------------------------------- */
 
-static void au_xib_clear_bit(struct inode *inode)
+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+                  ino_t ino)
 {
        int err, bit;
        unsigned long pindex;
-       struct super_block *sb;
        struct au_sbinfo *sbinfo;
 
-       AuDebugOn(inode->i_nlink);
-
-       sb = inode->i_sb;
-       xib_calc_bit(inode->i_ino, &pindex, &bit);
-       AuDebugOn(page_bits <= bit);
-       sbinfo = au_sbi(sb);
-       mutex_lock(&sbinfo->si_xib_mtx);
-       err = xib_pindex(sb, pindex);
-       if (!err) {
-               clear_bit(bit, sbinfo->si_xib_buf);
-               sbinfo->si_xib_next_bit = bit;
-       }
-       mutex_unlock(&sbinfo->si_xib_mtx);
-}
-
-/* for s_op->delete_inode() */
-void au_xino_delete_inode(struct inode *inode, const int unlinked)
-{
-       int err;
-       unsigned int mnt_flags;
-       aufs_bindex_t bindex, bend, bi;
-       unsigned char try_trunc;
-       struct au_iinfo *iinfo;
-       struct super_block *sb;
-       struct au_hinode *hi;
-       struct inode *h_inode;
-       struct au_branch *br;
-       au_writef_t xwrite;
-
-       sb = inode->i_sb;
-       mnt_flags = au_mntflags(sb);
-       if (!au_opt_test(mnt_flags, XINO)
-           || inode->i_ino == AUFS_ROOT_INO)
-               return;
+       if (!au_opt_test(au_mntflags(sb), XINO))
+               return 0;
 
-       if (unlinked) {
-               au_xigen_inc(inode);
-               au_xib_clear_bit(inode);
+       err = 0;
+       if (ino) {
+               sbinfo = au_sbi(sb);
+               xib_calc_bit(ino, &pindex, &bit);
+               AuDebugOn(page_bits <= bit);
+               mutex_lock(&sbinfo->si_xib_mtx);
+               err = xib_pindex(sb, pindex);
+               if (!err) {
+                       clear_bit(bit, sbinfo->si_xib_buf);
+                       sbinfo->si_xib_next_bit = bit;
+               }
+               mutex_unlock(&sbinfo->si_xib_mtx);
        }
 
-       iinfo = au_ii(inode);
-       if (!iinfo)
-               return;
-
-       bindex = iinfo->ii_bstart;
-       if (bindex < 0)
-               return;
-
-       xwrite = au_sbi(sb)->si_xwrite;
-       try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
-       hi = iinfo->ii_hinode + bindex;
-       bend = iinfo->ii_bend;
-       for (; bindex <= bend; bindex++, hi++) {
-               h_inode = hi->hi_inode;
-               if (!h_inode
-                   || (!unlinked && h_inode->i_nlink))
-                       continue;
-
-               /* inode may not be revalidated */
-               bi = au_br_index(sb, hi->hi_id);
-               if (bi < 0)
-                       continue;
-
-               br = au_sbr(sb, bi);
-               err = au_xino_do_write(xwrite, br->br_xino.xi_file,
-                                      h_inode->i_ino, /*ino*/0);
-               if (!err && try_trunc
-                   && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
-                       xino_try_trunc(sb, br);
-       }
+       if (!err)
+               err = au_xino_write(sb, bindex, h_ino, 0);
+       return err;
 }
 
 /* get an unused inode number from bitmap */