]> git.pld-linux.org Git - packages/kernel.git/commitdiff
- switch aufs2 to aufs2.1 (aufs2 is unmaintained)
authorJan Rękorajski <baggins@pld-linux.org>
Fri, 1 Oct 2010 12:09:30 +0000 (12:09 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
- resolve conflict between aufs2.1 and reiser4 (symbol exported by both patches)

Changed files:
    kernel-aufs2-reiser4.patch -> 1.1
    kernel-aufs2.patch -> 1.9
    kernel.spec -> 1.832

kernel-aufs2-reiser4.patch [new file with mode: 0644]
kernel-aufs2.patch
kernel.spec

diff --git a/kernel-aufs2-reiser4.patch b/kernel-aufs2-reiser4.patch
new file mode 100644 (file)
index 0000000..3f2c0f0
--- /dev/null
@@ -0,0 +1,12 @@
+diff --git a/fs/inode.c b/fs/inode.c
+index 722860b..bfb0698 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -84,7 +84,6 @@ static struct hlist_head *inode_hashtable __read_mostly;
+  * the i_state of an inode while it is in use..
+  */
+ DEFINE_SPINLOCK(inode_lock);
+-EXPORT_SYMBOL_GPL(inode_lock);
+ /*
+  * iprune_sem provides exclusion between the kswapd or try_to_free_pages
index 7c27120263aa22805983df5a0bd30bb336f68dcc..1cb3595606aaa662440d9ebb5cccdcd9a006c10a 100644 (file)
@@ -1,4 +1,4 @@
-aufs2 kbuild patch for linux-2.6.35
+aufs2.1 kbuild patch for linux-2.6.35
 
 diff --git a/fs/Kconfig b/fs/Kconfig
 index 5f85b59..6ee7cf8 100644
@@ -33,7 +33,7 @@ index 2fc8e14..3b766a7 100644
  header-y += auto_fs4.h
  header-y += ax25.h
  header-y += b1lli.h
-aufs2 base patch for linux-2.6.35
+aufs2.1 base patch for linux-2.6.35
 
 diff --git a/fs/namei.c b/fs/namei.c
 index 868d0cb..6e92c81 100644
@@ -114,8 +114,40 @@ index 997c3b4..be9a153 100644
 +                       unsigned int flags);
 +
  #endif
-aufs2 standalone patch for linux-2.6.35
+aufs2.1 standalone patch for linux-2.6.35
 
+diff --git a/fs/file_table.c b/fs/file_table.c
+index 5c7d10e..9031acf 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -34,6 +34,7 @@ struct files_stat_struct files_stat = {
+ /* public. Not pretty! */
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock);
++EXPORT_SYMBOL(files_lock);
+ /* SLAB cache for file structures */
+ static struct kmem_cache *filp_cachep __read_mostly;
+@@ -346,6 +347,7 @@ void file_kill(struct file *file)
+               file_list_unlock();
+       }
+ }
++EXPORT_SYMBOL(file_kill);
+ int fs_may_remount_ro(struct super_block *sb)
+ {
+diff --git a/fs/inode.c b/fs/inode.c
+index 722860b..bfb0698 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -84,6 +84,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
+  * the i_state of an inode while it is in use..
+  */
+ DEFINE_SPINLOCK(inode_lock);
++EXPORT_SYMBOL(inode_lock);
+ /*
+  * iprune_sem provides exclusion between the kswapd or try_to_free_pages
 diff --git a/fs/namei.c b/fs/namei.c
 index 6e92c81..334130e 100644
 --- a/fs/namei.c
@@ -388,7 +420,7 @@ index 351942a..6ba84a8 100644
                            unsigned long prot)
 diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
 --- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs    1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/ABI/testing/debugfs-aufs       2010-08-21 21:00:02.956499131 +0200
++++ linux/Documentation/ABI/testing/debugfs-aufs       2010-10-01 13:09:26.340878164 +0200
 @@ -0,0 +1,37 @@
 +What:         /debug/aufs/si_<id>/
 +Date:         March 2009
@@ -429,7 +461,7 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Document
 +              will be empty. About XINO files, see the aufs manual.
 diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
 --- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs      1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/ABI/testing/sysfs-aufs 2010-08-21 21:00:02.956499131 +0200
++++ linux/Documentation/ABI/testing/sysfs-aufs 2010-10-01 13:09:26.340878164 +0200
 @@ -0,0 +1,24 @@
 +What:         /sys/fs/aufs/si_<id>/
 +Date:         March 2009
@@ -457,7 +489,7 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentat
 +              will be empty. About XINO files, see the aufs manual.
 diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
 --- /usr/share/empty/fs/aufs/aufs.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/aufs.h       2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/aufs.h       2010-10-01 13:09:26.342878167 +0200
 @@ -0,0 +1,61 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -522,8 +554,8 @@ diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
 +#endif /* __AUFS_H__ */
 diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 --- /usr/share/empty/fs/aufs/branch.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/branch.c     2010-08-21 21:00:02.972333781 +0200
-@@ -0,0 +1,1005 @@
++++ linux/fs/aufs/branch.c     2010-10-01 13:09:26.343878167 +0200
+@@ -0,0 +1,1008 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -669,9 +701,9 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +
 +      kfree(add_branch->br_wbr);
 +
-+ out_br:
++out_br:
 +      kfree(add_branch);
-+ out:
++out:
 +      return ERR_PTR(err);
 +}
 +
@@ -689,7 +721,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +      err = -EINVAL;
 +      pr_err("write permission for readonly mount or inode, %s\n", path);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -779,7 +811,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +                                 (h_inode->i_mode & S_IALLUGO));
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -859,7 +891,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +                     AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
 +                     kst.f_namelen);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -900,9 +932,9 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +      mntget(add->path.mnt);
 +      goto out; /* success */
 +
-+ out_err:
++out_err:
 +      br->br_mnt = NULL;
-+ out:
++out:
 +      return err;
 +}
 +
@@ -962,7 +994,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +
 +      root = sb->s_root;
 +      root_inode = root->d_inode;
-+      au_plink_maint_block(sb);
 +      bend = au_sbend(sb);
 +      amount = bend + 1 - bindex;
 +      au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
@@ -1032,7 +1063,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +          && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
 +              au_xino_brid_set(sb, add_branch->br_id);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -1101,9 +1132,9 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +              }
 +      }
 +
-+ out_dpages:
++out_dpages:
 +      au_dpages_free(&dpages);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -1240,7 +1271,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +
 +      root = sb->s_root;
 +      inode = root->d_inode;
-+      au_plink_maint_block(sb);
 +      sbinfo = au_sbi(sb);
 +      bend = sbinfo->si_bend;
 +
@@ -1285,8 +1315,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +      i = atomic_read(&br->br_count);
 +      if (unlikely(i)) {
 +              AuVerbose(verbose, "%d file(s) opened\n", i);
-+              if (!verbose)
-+                      goto out;
++              goto out;
 +      }
 +
 +      wbr = br->br_wbr;
@@ -1329,13 +1358,13 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +              au_xino_brid_set(sb, -1);
 +      goto out; /* success */
 +
-+ out_wh:
++out_wh:
 +      /* revert */
 +      rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
 +      if (rerr)
 +              pr_warning("failed re-creating base whiteout, %s. (%d)\n",
 +                         del->pathname, rerr);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -1349,7 +1378,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +{
 +#ifdef CONFIG_IMA
 +      /* since it doesn't support mark_files_ro() */
-+      pr_warning("RW -> RO makes IMA to produce wrong message");
++      AuWarn1("RW -> RO makes IMA to produce wrong message");
 +#endif
 +}
 +
@@ -1368,8 +1397,11 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +{
 +      int err;
 +      unsigned long n, ul, bytes, files;
-+      aufs_bindex_t bstart;
++      aufs_bindex_t br_id;
 +      struct file *file, *hf, **a;
++      struct dentry *dentry;
++      struct inode *inode;
++      struct au_hfile *hfile;
 +      const int step_bytes = 1024, /* memory allocation unit */
 +              step_files = step_bytes / sizeof(*a);
 +
@@ -1382,9 +1414,12 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +              goto out;
 +
 +      /* no need file_list_lock() since sbinfo is locked? defered? */
++      br_id = au_sbr_id(sb, bindex);
 +      list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
 +              if (special_file(file->f_dentry->d_inode->i_mode))
 +                      continue;
++              dentry = file->f_dentry;
++              inode = dentry->d_inode;
 +
 +              AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
 +              fi_read_lock(file);
@@ -1395,16 +1430,17 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +                      goto out_free;
 +              }
 +
-+              bstart = au_fbstart(file);
-+              if (!S_ISREG(file->f_dentry->d_inode->i_mode)
++              hfile = &au_fi(file)->fi_htop;
++              hf = hfile->hf_file;
++              if (!S_ISREG(inode->i_mode)
 +                  || !(file->f_mode & FMODE_WRITE)
-+                  || bstart != bindex) {
++                  || hfile->hf_br->br_id != br_id
++                  || !(hf->f_mode & FMODE_WRITE)) {
 +                      FiMustNoWaiters(file);
 +                      fi_read_unlock(file);
 +                      continue;
 +              }
 +
-+              hf = au_hf_top(file);
 +              FiMustNoWaiters(file);
 +              fi_read_unlock(file);
 +
@@ -1439,9 +1475,9 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +              }
 +      }
 +
-+ out_free:
++out_free:
 +      kfree(a);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -1455,7 +1491,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +      struct au_branch *br;
 +
 +      root = sb->s_root;
-+      au_plink_maint_block(sb);
 +      bindex = au_find_dbindex(root, mod->h_root);
 +      if (bindex < 0) {
 +              if (remount)
@@ -1526,12 +1561,12 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +              br->br_perm = mod->perm;
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
 --- /usr/share/empty/fs/aufs/branch.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/branch.h     2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/branch.h     2010-10-01 13:09:26.343878167 +0200
 @@ -0,0 +1,224 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -1730,7 +1765,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
 +
 +static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
 +{
-+      atomic_dec_return(&au_sbr(sb, bindex)->br_count);
++      atomic_dec(&au_sbr(sb, bindex)->br_count);
 +}
 +
 +static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
@@ -1759,8 +1794,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
 +#endif /* __AUFS_BRANCH_H__ */
 diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
 --- /usr/share/empty/fs/aufs/conf.mk   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/conf.mk      2010-08-21 21:00:02.972333781 +0200
-@@ -0,0 +1,36 @@
++++ linux/fs/aufs/conf.mk      2010-10-01 13:09:26.343878167 +0200
+@@ -0,0 +1,37 @@
 +
 +AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
 +
@@ -1771,6 +1806,7 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
 +endef
 +
 +AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
++      SBILIST \
 +      HNOTIFY HFSNOTIFY HINOTIFY \
 +      EXPORT INO_T_64 \
 +      RDU \
@@ -1799,7 +1835,7 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
 +-include ${srctree}/${src}/conf_priv.mk
 diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 --- /usr/share/empty/fs/aufs/cpup.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/cpup.c       2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/cpup.c       2010-10-01 13:09:26.343878167 +0200
 @@ -0,0 +1,1059 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -2115,7 +2151,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +      else
 +              free_page((unsigned long)buf);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -2170,13 +2206,13 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +      IMustLock(file[SRC].dentry->d_inode);
 +      err = au_copy_file(file[DST].file, file[SRC].file, len);
 +
-+ out_dst:
++out_dst:
 +      fput(file[DST].file);
 +      au_sbr_put(sb, file[DST].bindex);
-+ out_src:
++out_src:
 +      fput(file[SRC].file);
 +      au_sbr_put(sb, file[SRC].bindex);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -2203,7 +2239,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +              err = -EIO;
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -2238,7 +2274,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +      }
 +      __putname(sym.k);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -2459,7 +2495,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +              err = -EIO;
 +      }
 +
-+ out:
++out:
 +      dput(dst_parent);
 +      return err;
 +}
@@ -2672,9 +2708,9 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +      au_dtime_revert(&dt);
 +      au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
 +
-+ out_wh:
++out_wh:
 +      dput(wh_dentry);
-+ out:
++out:
 +      dput(parent);
 +      return err;
 +}
@@ -2820,7 +2856,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +                      break;
 +      }
 +
-+ out:
++out:
 +      dput(parent);
 +      return err;
 +}
@@ -2856,13 +2892,13 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +              err = au_cpup_dirs(dentry, bdst);
 +      di_downgrade_lock(parent, AuLock_IR);
 +
-+ out:
++out:
 +      dput(parent);
 +      return err;
 +}
 diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
 --- /usr/share/empty/fs/aufs/cpup.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/cpup.h       2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/cpup.h       2010-10-01 13:09:26.343878167 +0200
 @@ -0,0 +1,81 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -2947,7 +2983,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
 +#endif /* __AUFS_CPUP_H__ */
 diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 --- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dbgaufs.c    2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/dbgaufs.c    2010-10-01 13:09:26.343878167 +0200
 @@ -0,0 +1,334 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -3031,7 +3067,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +              err = 0;
 +      }
 +
-+ out:
++out:
 +      return err;
 +
 +}
@@ -3102,7 +3138,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +              err = -ENOENT;
 +      si_read_unlock(sb);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -3260,9 +3296,9 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +      if (!err)
 +              goto out; /* success */
 +
-+ out_dir:
++out_dir:
 +      dbgaufs_si_fin(sbinfo);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -3285,7 +3321,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +}
 diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
 --- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dbgaufs.h    2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/dbgaufs.h    2010-10-01 13:09:26.343878167 +0200
 @@ -0,0 +1,52 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -3341,7 +3377,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
 +#endif /* __DBGAUFS_H__ */
 diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 --- /usr/share/empty/fs/aufs/dcsub.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dcsub.c      2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/dcsub.c      2010-10-01 13:09:26.343878167 +0200
 @@ -0,0 +1,200 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -3397,9 +3433,9 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +      dpages->ndpage = 1;
 +      return 0; /* success */
 +
-+ out_dpages:
++out_dpages:
 +      kfree(dpages->dpages);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -3446,7 +3482,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +      dpage->dentries[dpage->ndentry++] = dget(dentry);
 +      return 0; /* success */
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -3460,9 +3496,9 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +
 +      err = 0;
 +      spin_lock(&dcache_lock);
-+ repeat:
++repeat:
 +      next = this_parent->d_subdirs.next;
-+ resume:
++resume:
 +      if (this_parent->d_sb == sb
 +          && !IS_ROOT(this_parent)
 +          && atomic_read(&this_parent->d_count)
@@ -3498,7 +3534,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +              this_parent = this_parent->d_parent; /* dcache_lock is locked */
 +              goto resume;
 +      }
-+ out:
++out:
 +      spin_unlock(&dcache_lock);
 +      return err;
 +}
@@ -3524,7 +3560,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +              }
 +      }
 +
-+ out:
++out:
 +      spin_unlock(&dcache_lock);
 +
 +      return err;
@@ -3545,7 +3581,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +}
 diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
 --- /usr/share/empty/fs/aufs/dcsub.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dcsub.h      2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/dcsub.h      2010-10-01 13:09:26.343878167 +0200
 @@ -0,0 +1,54 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -3603,8 +3639,8 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
 +#endif /* __AUFS_DCSUB_H__ */
 diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 --- /usr/share/empty/fs/aufs/debug.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/debug.c      2010-08-21 21:00:02.972333781 +0200
-@@ -0,0 +1,440 @@
++++ linux/fs/aufs/debug.c      2010-10-01 13:09:26.344878166 +0200
+@@ -0,0 +1,443 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -3636,9 +3672,11 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 +module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
 +
 +char *au_plevel = KERN_DEBUG;
-+#define dpri(fmt, ...) do { \
-+      if (au_debug_test()) \
-+              printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
++#define dpri(fmt, ...) do {                                   \
++      if ((au_plevel                                          \
++           && strcmp(au_plevel, KERN_DEBUG))                  \
++          || au_debug_test())                                 \
++              printk("%s" fmt, au_plevel, ##__VA_ARGS__);     \
 +} while (0)
 +
 +/* ---------------------------------------------------------------------- */
@@ -3798,8 +3836,8 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 +          && file->f_dentry
 +          && au_test_aufs(file->f_dentry->d_sb)
 +          && au_fi(file))
-+              snprintf(a, sizeof(a), ", mmapped %d",
-+                       !!au_fi(file)->fi_hvmop);
++              snprintf(a, sizeof(a), ", gen %d, mmapped %d",
++                       au_figen(file), !!au_fi(file)->fi_hvmop);
 +      dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
 +           bindex, file->f_mode, file->f_flags, (long)file_count(file),
 +           file->f_version, file->f_pos, a);
@@ -3829,7 +3867,8 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 +      if (!fidir)
 +              do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
 +      else
-+              for (bindex = finfo->fi_btop; bindex <= fidir->fd_bbot;
++              for (bindex = finfo->fi_btop;
++                   bindex >= 0 && bindex <= fidir->fd_bbot;
 +                   bindex++) {
 +                      hfile = fidir->fd_hfile + bindex;
 +                      do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
@@ -3859,7 +3898,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 +           atomic_read(&sb->s_active), !!br->br_xino.xi_file);
 +      return 0;
 +
-+ out:
++out:
 +      dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
 +      return -1;
 +}
@@ -4047,7 +4086,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 +}
 diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
 --- /usr/share/empty/fs/aufs/debug.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/debug.h      2010-08-21 21:00:02.972333781 +0200
++++ linux/fs/aufs/debug.h      2010-10-01 13:09:26.444878166 +0200
 @@ -0,0 +1,245 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -4085,7 +4124,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
 +/* #include <linux/kernel.h> */
 +#include <linux/delay.h>
 +/* #include <linux/kd.h> */
-+/* #include <linux/vt_kern.h> */
++#include <linux/vt_kern.h>
 +#include <linux/sysrq.h>
 +#include <linux/aufs_type.h>
 +
@@ -4296,8 +4335,8 @@ diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
 +#endif /* __AUFS_DEBUG_H__ */
 diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 --- /usr/share/empty/fs/aufs/dentry.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dentry.c     2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,850 @@
++++ linux/fs/aufs/dentry.c     2010-10-01 13:09:26.444878166 +0200
+@@ -0,0 +1,860 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -4424,7 +4463,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +      if (!allow_neg)
 +              return NULL; /* success */
 +
-+ real_lookup:
++real_lookup:
 +      h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
 +      if (IS_ERR(h_dentry))
 +              goto out;
@@ -4459,10 +4498,10 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +      }
 +      goto out;
 +
-+ out_neg:
++out_neg:
 +      dput(h_dentry);
 +      h_dentry = NULL;
-+ out:
++out:
 +      return h_dentry;
 +}
 +
@@ -4569,10 +4608,10 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +              /* both of real entry and whiteout found */
 +              err = -EIO;
 +
-+ out_parent:
++out_parent:
 +      dput(parent);
 +      kfree(whname.name);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -4631,7 +4670,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +              au_set_dbend(dentry, bindex);
 +      au_set_h_dptr(dentry, bindex, h_dentry);
 +
-+ out:
++out:
 +      dput(parent);
 +      return err;
 +}
@@ -4713,7 +4752,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +              err = au_busy_or_stale();
 +      dput(h_d);
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -4850,9 +4889,9 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +      if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
 +              d_drop(dentry);
 +
-+ out_dgen:
++out_dgen:
 +      au_update_digen(dentry);
-+ out:
++out:
 +      dput(parent);
 +      AuTraceErr(npositive);
 +      return npositive;
@@ -4902,7 +4941,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +      else if (!valid)
 +              err = -EINVAL;
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -5089,10 +5128,19 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +      struct super_block *sb;
 +      struct inode *inode;
 +
-+      err = -EINVAL;
++      valid = 1;
 +      sb = dentry->d_sb;
 +      inode = dentry->d_inode;
-+      aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
++      /*
++       * todo: very ugly
++       * i_mutex of parent dir may be held,
++       * but we should not return 'invalid' due to busy.
++       */
++      err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
++      if (unlikely(err)) {
++              valid = err;
++              goto out;
++      }
 +      sigen = au_sigen(sb);
 +      if (au_digen(dentry) != sigen) {
 +              AuDebugOn(IS_ROOT(dentry));
@@ -5116,23 +5164,24 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +
 +              if (bstart >= 0
 +                  && au_test_higen(inode, au_h_iptr(inode, bstart)))
-+                      goto out;
++                      goto out_inval;
 +      }
 +
 +      err = h_d_revalidate(dentry, inode, nd, do_udba);
 +      if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
 +              /* both of real entry and whiteout found */
 +              err = -EIO;
-+      goto out;
++      goto out_inval;
 +
-+ out_dgrade:
++out_dgrade:
 +      di_downgrade_lock(dentry, AuLock_IR);
-+ out:
++out_inval:
 +      aufs_read_unlock(dentry, AuLock_IR);
 +      AuTraceErr(err);
 +      valid = !err;
++out:
 +      if (!valid)
-+              AuDbg("%.*s invalid\n", AuDLNPair(dentry));
++              AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
 +      return valid;
 +}
 +
@@ -5150,7 +5199,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +};
 diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
 --- /usr/share/empty/fs/aufs/dentry.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dentry.h     2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/dentry.h     2010-10-01 13:09:26.444878167 +0200
 @@ -0,0 +1,231 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -5370,7 +5419,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
 +#ifdef CONFIG_AUFS_HNOTIFY
 +static inline void au_digen_dec(struct dentry *d)
 +{
-+      atomic_dec_return(&au_di(d)->di_generation);
++      atomic_dec(&au_di(d)->di_generation);
 +}
 +
 +static inline void au_hn_di_reinit(struct dentry *dentry)
@@ -5385,8 +5434,8 @@ diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
 +#endif /* __AUFS_DENTRY_H__ */
 diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
 --- /usr/share/empty/fs/aufs/dinfo.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dinfo.c      2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,395 @@
++++ linux/fs/aufs/dinfo.c      2010-10-01 13:09:26.444878167 +0200
+@@ -0,0 +1,397 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -5411,11 +5460,13 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
 +
 +#include "aufs.h"
 +
-+void au_di_init_once(void *_di)
++void au_di_init_once(void *_dinfo)
 +{
-+      struct au_dinfo *di = _di;
++      struct au_dinfo *dinfo = _dinfo;
++      static struct lock_class_key aufs_di;
 +
-+      au_rw_init(&di->di_rwsem);
++      au_rw_init(&dinfo->di_rwsem);
++      au_rw_class(&dinfo->di_rwsem, &aufs_di);
 +}
 +
 +int au_di_init(struct dentry *dentry)
@@ -5448,9 +5499,9 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
 +      dentry->d_op = &aufs_dop;
 +      return 0; /* success */
 +
-+ out_dinfo:
++out_dinfo:
 +      au_cache_free_dinfo(dinfo);
-+ out:
++out:
 +      return -ENOMEM;
 +}
 +
@@ -5784,8 +5835,8 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
 +}
 diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 --- /usr/share/empty/fs/aufs/dir.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dir.c        2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,638 @@
++++ linux/fs/aufs/dir.c        2010-10-01 13:09:26.444878167 +0200
+@@ -0,0 +1,640 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -5920,7 +5971,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +      /* file->f_ra = h_file->f_ra; */
 +      err = 0;
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -5977,7 +6028,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +      err = -ENOMEM;
 +      sb = file->f_dentry->d_sb;
 +      si_read_lock(sb, AuLock_FLUSH);
-+      fidir = au_fidir_alloc(inode->i_sb);
++      fidir = au_fidir_alloc(sb);
 +      if (fidir) {
 +              err = au_do_open(file, do_open_dir, fidir);
 +              if (unlikely(err))
@@ -5996,11 +6047,13 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +      struct au_fidir *fidir;
 +      aufs_bindex_t bindex, bend;
 +
-+      au_plink_maint_leave(file);
 +      sb = file->f_dentry->d_sb;
 +      finfo = au_fi(file);
 +      fidir = finfo->fi_hdir;
 +      if (fidir) {
++              /* remove me from sb->s_files */
++              file_kill(file);
++
 +              vdir_cache = fidir->fd_vdir_cache; /* lock-free */
 +              if (vdir_cache)
 +                      au_vdir_free(vdir_cache);
@@ -6122,7 +6175,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +              }
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -6200,10 +6253,10 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +              return err;
 +      }
 +
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_write_unlock(file);
-+ out:
++out:
 +      si_read_unlock(sb);
 +      return err;
 +}
@@ -6258,7 +6311,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +                      (arg->whlist, name, namelen, ino, d_type, arg->bindex,
 +                       au_ftest_testempty(arg->flags, SHWH));
 +
-+ out:
++out:
 +      /* smp_mb(); */
 +      AuTraceErr(arg->err);
 +      return arg->err;
@@ -6290,10 +6343,10 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +                      err = arg->err;
 +      } while (!err && au_ftest_testempty(arg->flags, CALLED));
 +
-+ out_put:
++out_put:
 +      fput(h_file);
 +      au_sbr_put(dentry->d_sb, arg->bindex);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -6378,9 +6431,9 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +              }
 +      }
 +
-+ out_whlist:
++out_whlist:
 +      au_nhash_wh_free(&whlist);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -6426,7 +6479,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +};
 diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
 --- /usr/share/empty/fs/aufs/dir.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dir.h        2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/dir.h        2010-10-01 13:09:26.444878167 +0200
 @@ -0,0 +1,138 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -6568,7 +6621,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
 +#endif /* __AUFS_DIR_H__ */
 diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 --- /usr/share/empty/fs/aufs/dynop.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dynop.c      2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/dynop.c      2010-10-01 13:09:26.444878167 +0200
 @@ -0,0 +1,425 @@
 +/*
 + * Copyright (C) 2010 Junjiro R. Okajima
@@ -6712,7 +6765,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +
 +#ifdef CONFIG_AUFS_DEBUG
 +#define DyDbgDeclare(cnt)     unsigned int cnt = 0
-+#define DyDbgInc(cnt)         cnt++
++#define DyDbgInc(cnt)         do { cnt++; } while (0)
 +#else
 +#define DyDbgDeclare(cnt)     do {} while (0)
 +#define DyDbgInc(cnt)         do {} while (0)
@@ -6997,7 +7050,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +}
 diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
 --- /usr/share/empty/fs/aufs/dynop.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dynop.h      2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/dynop.h      2010-10-01 13:09:26.444878167 +0200
 @@ -0,0 +1,89 @@
 +/*
 + * Copyright (C) 2010 Junjiro R. Okajima
@@ -7090,7 +7143,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
 +#endif /* __AUFS_DYNOP_H__ */
 diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 --- /usr/share/empty/fs/aufs/export.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/export.c     2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/export.c     2010-10-01 13:09:26.444878167 +0200
 @@ -0,0 +1,788 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -7257,7 +7310,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +              AuIOErr("xigen error (%zd)\n", sz);
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -7279,7 +7332,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +              fput(sbinfo->si_xigen);
 +      sbinfo->si_xigen = file;
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -7335,9 +7388,9 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +              dentry = ERR_PTR(-ESTALE);
 +      }
 +
-+ out_iput:
++out_iput:
 +      iput(inode);
-+ out:
++out:
 +      return dentry;
 +}
 +
@@ -7404,7 +7457,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +              si_read_unlock(sb);
 +      bindex = -1;
 +
-+ out:
++out:
 +      return bindex;
 +}
 +
@@ -7480,11 +7533,11 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +              dentry = ERR_PTR(-ENOENT);
 +      }
 +
-+ out_name:
++out_name:
 +      __putname(arg.name);
-+ out_file:
++out_file:
 +      fput(file);
-+ out:
++out:
 +      if (unlikely(nsi_lock
 +                   && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
 +              if (!IS_ERR(dentry)) {
@@ -7515,7 +7568,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +      dentry = au_lkup_by_ino(&path, ino, nsi_lock);
 +      path_put(&path);
 +
-+ out:
++out:
 +      AuTraceErrPtr(dentry);
 +      return dentry;
 +}
@@ -7556,7 +7609,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +      if (n != 1)
 +              p[strlen(p)] = '/';
 +
-+ out:
++out:
 +      AuTraceErrPtr(p);
 +      return p;
 +}
@@ -7626,19 +7679,19 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +      else
 +              dentry = dget(path.dentry);
 +
-+ out_path:
++out_path:
 +      path_put(&path);
-+ out_relock:
++out_relock:
 +      if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
 +              if (!IS_ERR(dentry)) {
 +                      dput(dentry);
 +                      dentry = ERR_PTR(-ESTALE);
 +              }
-+ out_pathname:
++out_pathname:
 +      free_page((unsigned long)pathname);
-+ out_h_parent:
++out_h_parent:
 +      dput(h_parent);
-+ out:
++out:
 +      /* au_br_put(br); */
 +      AuTraceErrPtr(dentry);
 +      return dentry;
@@ -7699,15 +7752,15 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +              /* todo?: make it ESTALE */
 +              goto out_unlock;
 +
-+ accept:
++accept:
 +      if (dentry->d_inode->i_generation == fh[Fh_igen])
 +              goto out_unlock; /* success */
 +
 +      dput(dentry);
 +      dentry = ERR_PTR(-ESTALE);
-+ out_unlock:
++out_unlock:
 +      si_read_unlock(sb);
-+ out:
++out:
 +      AuTraceErrPtr(dentry);
 +      return dentry;
 +}
@@ -7729,7 +7782,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +              parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
 +                                      dir_ino, fh, fh_len);
 +
-+ out:
++out:
 +      AuTraceErrPtr(parent);
 +      return parent;
 +}
@@ -7812,13 +7865,13 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +      else
 +              AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
 +
-+ out_dput:
++out_dput:
 +      dput(h_parent);
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(parent, !AuLock_IR);
 +      dput(parent);
 +      aufs_read_unlock(dentry, AuLock_IR);
-+ out:
++out:
 +      if (unlikely(err < 0))
 +              err = 255;
 +      return err;
@@ -7835,7 +7888,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +      int (*f)(struct inode *inode);
 +
 +      sb = inode->i_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      ii_write_lock_child(inode);
 +      bindex = au_ibstart(inode);
 +      AuDebugOn(bindex < 0);
@@ -7882,7 +7935,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +}
 diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 --- /usr/share/empty/fs/aufs/file.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/file.c       2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/file.c       2010-10-01 13:09:26.467878166 +0200
 @@ -0,0 +1,652 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -7984,9 +8037,9 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +      fsnotify_open(h_dentry);
 +      goto out; /* success */
 +
-+ out_br:
++out_br:
 +      atomic_dec(&br->br_count);
-+ out:
++out:
 +      return h_file;
 +}
 +
@@ -8011,7 +8064,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +              au_finfo_fin(file);
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -8050,7 +8103,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +      /* todo: necessary? */
 +      /* file->f_ra = h_file->f_ra; */
 +
-+ out:
++out:
 +      if (h_file_tmp)
 +              fput(h_file_tmp);
 +      return err;
@@ -8179,13 +8232,13 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +      au_unpin(pin);
 +      goto out_unlock;
 +
-+ out_dgrade:
++out_dgrade:
 +      di_downgrade_lock(parent, AuLock_IR);
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(parent, AuLock_IR);
-+ out_dput:
++out_dput:
 +      dput(parent);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -8271,11 +8324,11 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +              *need_reopen = 0;
 +      }
 +
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(parent, AuLock_IR);
-+ out_parent:
++out_parent:
 +      dput(parent);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -8398,7 +8451,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +                      au_set_h_fptr(file, bindex, NULL);
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -8452,7 +8505,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +              fi_write_unlock(file);
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -8538,7 +8591,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +};
 diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
 --- /usr/share/empty/fs/aufs/file.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/file.h       2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/file.h       2010-10-01 13:09:26.467878166 +0200
 @@ -0,0 +1,238 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -8588,8 +8641,8 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
 +
 +static inline int au_fidir_sz(int nent)
 +{
-+       AuDebugOn(nent < 0);
-+       return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
++      AuDebugOn(nent < 0);
++      return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
 +}
 +
 +struct au_finfo {
@@ -8780,8 +8833,8 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
 +#endif /* __AUFS_FILE_H__ */
 diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 --- /usr/share/empty/fs/aufs/finfo.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/finfo.c      2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,167 @@
++++ linux/fs/aufs/finfo.c      2010-10-01 13:09:26.467878166 +0200
+@@ -0,0 +1,171 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -8814,7 +8867,7 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 +              allow_write_access(hf->hf_file);
 +      fput(hf->hf_file);
 +      hf->hf_file = NULL;
-+      atomic_dec_return(&hf->hf_br->br_count);
++      atomic_dec(&hf->hf_br->br_count);
 +      hf->hf_br = NULL;
 +}
 +
@@ -8916,13 +8969,17 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 +      au_cache_free_finfo(finfo);
 +}
 +
-+void au_fi_init_once(void *_fi)
++void au_fi_init_once(void *_finfo)
 +{
-+      struct au_finfo *fi = _fi;
++      struct au_finfo *finfo = _finfo;
++      static struct lock_class_key aufs_fi, aufs_fi_vm, aufs_fi_mmap;
 +
-+      au_rw_init(&fi->fi_rwsem);
-+      mutex_init(&fi->fi_vm_mtx);
-+      mutex_init(&fi->fi_mmap);
++      au_rw_init(&finfo->fi_rwsem);
++      au_rw_class(&finfo->fi_rwsem, &aufs_fi);
++      mutex_init(&finfo->fi_vm_mtx);
++      lockdep_set_class(&finfo->fi_vm_mtx, &aufs_fi_vm);
++      mutex_init(&finfo->fi_mmap);
++      lockdep_set_class(&finfo->fi_mmap, &aufs_fi_mmap);
 +}
 +
 +int au_finfo_init(struct file *file, struct au_fidir *fidir)
@@ -8951,8 +9008,8 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 +}
 diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 --- /usr/share/empty/fs/aufs/f_op.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/f_op.c       2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,886 @@
++++ linux/fs/aufs/f_op.c       2010-10-01 13:09:26.445878166 +0200
+@@ -0,0 +1,901 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -9035,8 +9092,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +
 +      finfo = au_fi(file);
 +      bindex = finfo->fi_btop;
-+      if (bindex >= 0)
++      if (bindex >= 0) {
++              /* remove me from sb->s_files */
++              file_kill(file);
 +              au_set_h_fptr(file, bindex, NULL);
++      }
 +
 +      au_finfo_fin(file);
 +      return 0;
@@ -9073,7 +9133,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +
 +      dentry = file->f_dentry;
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
 +      if (unlikely(err))
 +              goto out;
@@ -9086,11 +9146,33 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_read_unlock(file);
-+ out:
++out:
 +      si_read_unlock(sb);
 +      return err;
 +}
 +
++/*
++ * todo: very ugly
++ * it locks both of i_mutex and si_rwsem for read in safe.
++ * if the plink maintenance mode continues forever (that is the problem),
++ * may loop forever.
++ */
++static void au_mtx_and_read_lock(struct inode *inode)
++{
++      int err;
++      struct super_block *sb = inode->i_sb;
++
++      while (1) {
++              mutex_lock(&inode->i_mutex);
++              err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++              if (!err)
++                      break;
++              mutex_unlock(&inode->i_mutex);
++              si_read_lock(sb, AuLock_NOPLMW);
++              si_read_unlock(sb);
++      }
++}
++
 +static ssize_t aufs_write(struct file *file, const char __user *ubuf,
 +                        size_t count, loff_t *ppos)
 +{
@@ -9098,15 +9180,12 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      struct au_pin pin;
 +      struct dentry *dentry;
 +      struct inode *inode;
-+      struct super_block *sb;
 +      struct file *h_file;
 +      char __user *buf = (char __user *)ubuf;
 +
 +      dentry = file->f_dentry;
-+      sb = dentry->d_sb;
 +      inode = dentry->d_inode;
-+      mutex_lock(&inode->i_mutex);
-+      si_read_lock(sb, AuLock_FLUSH);
++      au_mtx_and_read_lock(inode);
 +
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
 +      if (unlikely(err))
@@ -9123,11 +9202,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      au_cpup_attr_timesizes(inode);
 +      inode->i_mode = h_file->f_dentry->d_inode->i_mode;
 +
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_write_unlock(file);
-+ out:
-+      si_read_unlock(sb);
++out:
++      si_read_unlock(inode->i_sb);
 +      mutex_unlock(&inode->i_mutex);
 +      return err;
 +}
@@ -9159,7 +9238,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +              /* currently there is no such fs */
 +              WARN_ON_ONCE(1);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -9174,7 +9253,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      file = kio->ki_filp;
 +      dentry = file->f_dentry;
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
 +      if (unlikely(err))
 +              goto out;
@@ -9187,7 +9266,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_read_unlock(file);
 +
-+ out:
++out:
 +      si_read_unlock(sb);
 +      return err;
 +}
@@ -9199,15 +9278,13 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      struct au_pin pin;
 +      struct dentry *dentry;
 +      struct inode *inode;
-+      struct super_block *sb;
 +      struct file *file, *h_file;
 +
 +      file = kio->ki_filp;
 +      dentry = file->f_dentry;
-+      sb = dentry->d_sb;
 +      inode = dentry->d_inode;
-+      mutex_lock(&inode->i_mutex);
-+      si_read_lock(sb, AuLock_FLUSH);
++      au_mtx_and_read_lock(inode);
++
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
 +      if (unlikely(err))
 +              goto out;
@@ -9223,11 +9300,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      au_cpup_attr_timesizes(inode);
 +      inode->i_mode = h_file->f_dentry->d_inode->i_mode;
 +
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_write_unlock(file);
-+ out:
-+      si_read_unlock(sb);
++out:
++      si_read_unlock(inode->i_sb);
 +      mutex_unlock(&inode->i_mutex);
 +      return err;
 +}
@@ -9243,7 +9320,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +
 +      dentry = file->f_dentry;
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
 +      if (unlikely(err))
 +              goto out;
@@ -9262,7 +9339,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_read_unlock(file);
 +
-+ out:
++out:
 +      si_read_unlock(sb);
 +      return err;
 +}
@@ -9275,15 +9352,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      struct au_pin pin;
 +      struct dentry *dentry;
 +      struct inode *inode;
-+      struct super_block *sb;
 +      struct file *h_file;
 +
 +      dentry = file->f_dentry;
 +      inode = dentry->d_inode;
-+      mutex_lock(&inode->i_mutex);
-+      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
-+
++      au_mtx_and_read_lock(inode);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
 +      if (unlikely(err))
 +              goto out;
@@ -9299,11 +9372,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      au_cpup_attr_timesizes(inode);
 +      inode->i_mode = h_file->f_dentry->d_inode->i_mode;
 +
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_write_unlock(file);
-+ out:
-+      si_read_unlock(sb);
++out:
++      si_read_unlock(inode->i_sb);
 +      mutex_unlock(&inode->i_mutex);
 +      return err;
 +}
@@ -9481,7 +9554,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +              h_vmop = ERR_PTR(-EIO);
 +      }
 +
-+ out:
++out:
 +      return h_vmop;
 +}
 +
@@ -9527,7 +9600,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +
 +      dentry = file->f_dentry;
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, !AuLock_FLUSH);
++      si_read_lock(sb, AuLock_NOPLMW);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
 +      if (unlikely(err))
 +              goto out;
@@ -9628,10 +9701,10 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      /* update without lock, I don't think it a problem */
 +      fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
 +
-+ out_unlock:
++out_unlock:
 +      au_fi_mmap_unlock(file);
 +      fput(args.h_file);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -9656,14 +9729,16 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      IMustLock(inode);
 +
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++      if (unlikely(err))
++              goto out;
 +
 +      err = 0; /* -EBADF; */ /* posix? */
 +      if (unlikely(!(file->f_mode & FMODE_WRITE)))
-+              goto out;
++              goto out_si;
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
 +      if (unlikely(err))
-+              goto out;
++              goto out_si;
 +
 +      err = au_ready_to_write(file, -1, &pin);
 +      di_downgrade_lock(dentry, AuLock_IR);
@@ -9690,11 +9765,12 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +              mutex_unlock(h_mtx);
 +      }
 +
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_write_unlock(file);
-+ out:
++out_si:
 +      si_read_unlock(sb);
++out:
 +      if (inode != file->f_mapping->host) {
 +              mutex_unlock(&inode->i_mutex);
 +              mutex_lock(&file->f_mapping->host->i_mutex);
@@ -9711,15 +9787,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      struct dentry *dentry;
 +      struct inode *inode;
 +      struct file *file, *h_file;
-+      struct super_block *sb;
 +
 +      file = kio->ki_filp;
 +      dentry = file->f_dentry;
 +      inode = dentry->d_inode;
-+      mutex_lock(&inode->i_mutex);
-+
-+      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      au_mtx_and_read_lock(inode);
 +
 +      err = 0; /* -EBADF; */ /* posix? */
 +      if (unlikely(!(file->f_mode & FMODE_WRITE)))
@@ -9756,11 +9828,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +              mutex_unlock(h_mtx);
 +      }
 +
-+ out_unlock:
++out_unlock:
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_write_unlock(file);
-+ out:
-+      si_read_unlock(sb);
++out:
++      si_read_unlock(inode->sb);
 +      mutex_unlock(&inode->i_mutex);
 +      return err;
 +}
@@ -9775,7 +9847,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +
 +      dentry = file->f_dentry;
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
 +      if (unlikely(err))
 +              goto out;
@@ -9787,7 +9859,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_read_unlock(file);
 +
-+ out:
++out:
 +      si_read_unlock(sb);
 +      return err;
 +}
@@ -9841,7 +9913,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +};
 diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
 --- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/f_op_sp.c    2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/f_op_sp.c    2010-10-01 13:09:26.445878166 +0200
 @@ -0,0 +1,299 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -9945,9 +10017,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
 +/* ---------------------------------------------------------------------- */
 +
 +/* currently, support only FIFO */
-+enum {AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
-+      /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
-+      AuSp_Last};
++enum {
++      AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
++      /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
++      AuSp_Last
++};
 +static int aufs_open_sp(struct inode *inode, struct file *file);
 +static struct au_sp_fop {
 +      int                     done;
@@ -10047,7 +10121,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
 +              au_unpin(&pin);
 +      }
 +
-+ out:
++out:
 +      di_downgrade_lock(dentry, AuLock_IR);
 +      return err;
 +}
@@ -10087,10 +10161,8 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
 +      di_read_lock_child(dentry, AuLock_IR);
 +      if (!err)
 +              au_init_fop_sp(file);
-+      else
-+              au_finfo_fin(file);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -10144,7 +10216,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
 +}
 diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 --- /usr/share/empty/fs/aufs/fstype.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/fstype.h     2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/fstype.h     2010-10-01 13:09:26.467878166 +0200
 @@ -0,0 +1,497 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -10645,7 +10717,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +#endif /* __AUFS_FSTYPE_H__ */
 diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
 --- /usr/share/empty/fs/aufs/hfsnotify.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/hfsnotify.c  2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/hfsnotify.c  2010-10-01 13:09:26.467878166 +0200
 @@ -0,0 +1,230 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -10879,7 +10951,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
 +};
 diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
 --- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/hfsplus.c    2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/hfsplus.c    2010-10-01 13:09:26.467878166 +0200
 @@ -0,0 +1,58 @@
 +/*
 + * Copyright (C) 2010 Junjiro R. Okajima
@@ -10941,8 +11013,8 @@ diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
 +}
 diff -urN /usr/share/empty/fs/aufs/hinotify.c linux/fs/aufs/hinotify.c
 --- /usr/share/empty/fs/aufs/hinotify.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/hinotify.c   2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,227 @@
++++ linux/fs/aufs/hinotify.c   2010-10-01 13:09:26.467878166 +0200
+@@ -0,0 +1,231 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -11071,7 +11143,9 @@ diff -urN /usr/share/empty/fs/aufs/hinotify.c linux/fs/aufs/hinotify.c
 +      u32 conv;
 +
 +      conv = 0;
-+#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0
++#define do_conv(flag) do {                                    \
++              conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0; \
++      } while (0)
 +      do_conv(ACCESS);
 +      do_conv(MODIFY);
 +      do_conv(ATTRIB);
@@ -11087,7 +11161,9 @@ diff -urN /usr/share/empty/fs/aufs/hinotify.c linux/fs/aufs/hinotify.c
 +      do_conv(UNMOUNT);
 +      do_conv(Q_OVERFLOW);
 +#undef do_conv
-+#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0
++#define do_conv(flag) do {                                            \
++              conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0;      \
++      } while (0)
 +      do_conv(IGNORED);
 +      /* do_conv(ISDIR); */
 +      /* do_conv(ONESHOT); */
@@ -11172,8 +11248,8 @@ diff -urN /usr/share/empty/fs/aufs/hinotify.c linux/fs/aufs/hinotify.c
 +};
 diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 --- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/hnotify.c    2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,663 @@
++++ linux/fs/aufs/hnotify.c    2010-10-01 13:09:26.467878166 +0200
+@@ -0,0 +1,662 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -11316,7 +11392,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +
 +      /* children inode number will be broken */
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -11355,13 +11431,13 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +              }
 +      }
 +
-+ out_dpages:
++out_dpages:
 +      au_dpages_free(&dpages);
 +
 +      /* discard children */
 +      dentry_unhash(dentry);
 +      dput(dentry);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -11413,7 +11489,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +              dput(d);
 +      }
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -11592,7 +11668,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +
 +      ii_write_lock_child(inode);
 +
-+ out:
++out:
 +      return inode;
 +}
 +
@@ -11627,8 +11703,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +      AuDebugOn(!sb);
 +      sbinfo = au_sbi(sb);
 +      AuDebugOn(!sbinfo);
-+      /* big aufs lock */
-+      si_noflush_write_lock(sb);
++      si_write_lock(sb, !AuLock_FLUSH | AuLock_NOPLMW);
 +
 +      ii_read_lock_parent(a->dir);
 +      bfound = -1;
@@ -11694,7 +11769,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +      err = hn_job(&args);
 +      ii_write_unlock(a->dir);
 +
-+ out:
++out:
 +      au_nwt_done(&sbinfo->si_nowait);
 +      si_write_unlock(sb);
 +
@@ -11839,8 +11914,8 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +}
 diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
 --- /usr/share/empty/fs/aufs/iinfo.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/iinfo.c      2010-08-21 21:00:02.980020464 +0200
-@@ -0,0 +1,257 @@
++++ linux/fs/aufs/iinfo.c      2010-10-01 13:09:26.468878166 +0200
+@@ -0,0 +1,259 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -12003,8 +12078,10 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
 +{
 +      struct au_icntnr *c = _c;
 +      struct au_iinfo *iinfo = &c->iinfo;
++      static struct lock_class_key aufs_ii;
 +
 +      au_rw_init(&iinfo->ii_rwsem);
++      au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
 +      inode_init_once(&c->vfs_inode);
 +}
 +
@@ -12100,7 +12177,7 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
 +}
 diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 --- /usr/share/empty/fs/aufs/inode.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/inode.c      2010-08-21 21:00:02.980020464 +0200
++++ linux/fs/aufs/inode.c      2010-10-01 13:09:26.469878166 +0200
 @@ -0,0 +1,443 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -12130,7 +12207,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +{
 +      if (inode) {
 +              AuDebugOn(!atomic_read(&inode->i_count));
-+              atomic_inc_return(&inode->i_count);
++              atomic_inc(&inode->i_count);
 +      }
 +      return inode;
 +}
@@ -12200,7 +12277,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +      if (do_attr)
 +              au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -12253,7 +12330,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +              err = e;
 +      au_refresh_hinode_attr(inode, update && isdir);
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -12327,7 +12404,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +      }
 +      au_cpup_attr_all(inode, /*force*/1);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -12366,7 +12443,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +
 +      if (unlikely(err))
 +              ii_write_unlock(inode);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -12396,7 +12473,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +                      goto out;
 +      }
 +
-+ out:
++out:
 +      if (mtx)
 +              mutex_unlock(mtx);
 +      return err;
@@ -12428,7 +12505,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +      if (!S_ISDIR(h_inode->i_mode))
 +              mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
 +
-+ new_ino:
++new_ino:
 +      if (mtx)
 +              mutex_lock(mtx);
 +      err = au_xino_read(sb, bstart, h_ino, &ino);
@@ -12494,11 +12571,11 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +              goto new_ino;
 +      }
 +
-+ out_iput:
++out_iput:
 +      iput(inode);
-+ out_err:
++out_err:
 +      inode = ERR_PTR(err);
-+ out:
++out:
 +      if (mtx)
 +              mutex_unlock(mtx);
 +      return inode;
@@ -12547,8 +12624,8 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
 +}
 diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
 --- /usr/share/empty/fs/aufs/inode.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/inode.h      2010-08-21 21:00:02.980020464 +0200
-@@ -0,0 +1,498 @@
++++ linux/fs/aufs/inode.h      2010-10-01 13:09:26.469878166 +0200
+@@ -0,0 +1,514 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -12757,9 +12834,11 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
 +void au_iinfo_fin(struct inode *inode);
 +int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
 +
++#ifdef CONFIG_PROC_FS
 +/* plink.c */
-+void au_plink_maint_block(struct super_block *sb);
-+void au_plink_maint_leave(struct file *file);
++int au_plink_maint(struct super_block *sb, int flags);
++void au_plink_maint_leave(struct au_sbinfo *sbinfo);
++int au_plink_maint_enter(struct super_block *sb);
 +#ifdef CONFIG_AUFS_DEBUG
 +void au_plink_list(struct super_block *sb);
 +#else
@@ -12769,9 +12848,23 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
 +struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
 +void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
 +                   struct dentry *h_dentry);
-+void au_plink_put(struct super_block *sb);
++void au_plink_put(struct super_block *sb, int verbose);
++void au_plink_clean(struct super_block *sb, int verbose);
 +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
-+long au_plink_ioctl(struct file *file, unsigned int cmd);
++#else
++AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
++AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
++AuStubInt0(au_plink_maint_enter, struct super_block *sb);
++AuStubVoid(au_plink_list, struct super_block *sb);
++AuStubInt0(au_plink_test, struct inode *inode);
++AuStub(struct dentry *, au_plink_lkup, return NULL,
++       struct inode *inode, aufs_bindex_t bindex);
++AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
++         struct dentry *h_dentry);
++AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
++AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
++AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
++#endif /* CONFIG_PROC_FS */
 +
 +/* ---------------------------------------------------------------------- */
 +
@@ -12854,7 +12947,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
 +static inline void au_iigen_dec(struct inode *inode)
 +{
 +#ifdef CONFIG_AUFS_HNOTIFY
-+      atomic_dec_return(&au_ii(inode)->ii_generation);
++      atomic_dec(&au_ii(inode)->ii_generation);
 +#endif
 +}
 +
@@ -13049,8 +13142,8 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
 +#endif /* __AUFS_INODE_H__ */
 diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
 --- /usr/share/empty/fs/aufs/ioctl.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/ioctl.c      2010-08-21 21:00:02.980020464 +0200
-@@ -0,0 +1,155 @@
++++ linux/fs/aufs/ioctl.c      2010-10-01 13:09:26.469878166 +0200
+@@ -0,0 +1,150 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -13122,9 +13215,9 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
 +      err = fd;
 +      goto out; /* success */
 +
-+ out_fd:
++out_fd:
 +      put_unused_fd(fd);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -13135,11 +13228,6 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
 +      long err;
 +
 +      switch (cmd) {
-+      case AUFS_CTL_PLINK_MAINT:
-+      case AUFS_CTL_PLINK_CLEAN:
-+              err = au_plink_ioctl(file, cmd);
-+              break;
-+
 +      case AUFS_CTL_RDU:
 +      case AUFS_CTL_RDU_INO:
 +              err = au_rdu_ioctl(file, cmd, arg);
@@ -13208,8 +13296,8 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
 +#endif
 diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 --- /usr/share/empty/fs/aufs/i_op_add.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op_add.c   2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,672 @@
++++ linux/fs/aufs/i_op_add.c   2010-10-01 13:09:26.468878166 +0200
+@@ -0,0 +1,676 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -13289,7 +13377,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +      } else
 +              dput(wh);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -13337,7 +13425,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +      if (unlikely(h_parent != h_dentry->d_parent))
 +              err = -EIO;
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -13401,10 +13489,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +
 +      wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
 +
-+ out_unpin:
++out_unpin:
 +      if (IS_ERR(wh_dentry))
 +              au_unpin(pin);
-+ out:
++out:
 +      return wh_dentry;
 +}
 +
@@ -13493,7 +13581,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +      au_unpin(&pin);
 +      dput(wh_dentry);
 +
-+ out:
++out:
 +      if (unlikely(err)) {
 +              au_update_dbstart(dentry);
 +              d_drop(dentry);
@@ -13578,7 +13666,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +      au_h_open_post(src_dentry, a->bsrc, h_file);
 +      au_unpin(&a->pin);
 +
-+ out:
++out:
 +      di_read_unlock(a->src_parent, AuLock_IR);
 +      return err;
 +}
@@ -13678,7 +13766,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +              goto out;
 +
 +      a->parent = dentry->d_parent; /* dir inode is locked */
-+      aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
++      err = aufs_read_and_write_lock2(dentry, src_dentry, AuLock_NOPLM);
++      if (unlikely(err))
++              goto out_kfree;
++
 +      a->src_parent = dget_parent(src_dentry);
 +      wr_dir_args.force_btgt = au_dbstart(src_dentry);
 +
@@ -13755,21 +13846,21 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +              d_drop(dentry);
 +      goto out_unpin; /* success */
 +
-+ out_revert:
++out_revert:
 +      rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
 +      if (!rerr)
 +              goto out_dt;
 +      AuIOErr("%.*s reverting failed(%d, %d)\n",
 +              AuDLNPair(dentry), err, rerr);
 +      err = -EIO;
-+ out_dt:
++out_dt:
 +      d_drop(dentry);
 +      au_dtime_revert(&dt);
-+ out_unpin:
++out_unpin:
 +      au_unpin(&a->pin);
-+ out_wh:
++out_wh:
 +      dput(wh_dentry);
-+ out_unlock:
++out_unlock:
 +      if (unlikely(err)) {
 +              au_update_dbstart(dentry);
 +              d_drop(dentry);
@@ -13777,8 +13868,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +      di_write_unlock(a->parent);
 +      dput(a->src_parent);
 +      aufs_read_and_write_unlock2(dentry, src_dentry);
++out_kfree:
 +      kfree(a);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -13858,7 +13950,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +              }
 +      }
 +
-+ out_dir:
++out_dir:
 +      AuLabel(revert dir);
 +      rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
 +      if (rerr) {
@@ -13868,10 +13960,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +      }
 +      d_drop(dentry);
 +      au_dtime_revert(&a->dt);
-+ out_unlock:
++out_unlock:
 +      au_unpin(&a->pin);
 +      dput(wh_dentry);
-+ out_free:
++out_free:
 +      if (unlikely(err)) {
 +              au_update_dbstart(dentry);
 +              d_drop(dentry);
@@ -13879,13 +13971,13 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +      di_write_unlock(parent);
 +      aufs_read_unlock(dentry, AuLock_DW);
 +      kfree(a);
-+ out:
++out:
 +      return err;
 +}
 diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 --- /usr/share/empty/fs/aufs/i_op.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op.c       2010-08-21 21:00:02.975972487 +0200
-@@ -0,0 +1,916 @@
++++ linux/fs/aufs/i_op.c       2010-10-01 13:09:26.468878166 +0200
+@@ -0,0 +1,922 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -13968,7 +14060,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      }
 +#endif
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -14028,7 +14120,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +              }
 +      }
 +
-+ out:
++out:
 +      ii_read_unlock(inode);
 +      si_read_unlock(sb);
 +      return err;
@@ -14077,9 +14169,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      if (unlikely(IS_ERR(ret) && inode))
 +              ii_write_unlock(inode);
 +
-+ out_unlock:
++out_unlock:
 +      di_write_unlock(dentry);
-+ out:
++out:
 +      si_read_unlock(sb);
 +      return ret;
 +}
@@ -14189,7 +14281,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      /* copyup the new parent into the branch we process */
 +      err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
 +
-+ out:
++out:
 +      dput(parent);
 +      return err;
 +}
@@ -14205,7 +14297,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +
 +void au_unpin(struct au_pin *p)
 +{
-+      if (au_ftest_pin(p->flags, MNT_WRITE))
++      if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
 +              mnt_drop_write(p->h_mnt);
 +      if (!p->hdir)
 +              return;
@@ -14263,6 +14355,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +       * and h_parent can be NULL.
 +       */
 +      if (unlikely(!p->hdir || !h_dir || !h_parent)) {
++              err = -EBUSY;
 +              if (!au_ftest_pin(p->flags, DI_LOCKED))
 +                      di_read_unlock(p->parent, AuLock_IR);
 +              dput(p->parent);
@@ -14295,12 +14388,12 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      }
 +      goto out; /* success */
 +
-+ out_unpin:
++out_unpin:
 +      au_unpin(p);
-+ out_err:
++out_err:
 +      pr_err("err %d\n", err);
 +      err = au_busy_or_stale();
-+ out:
++out:
 +      return err;
 +}
 +
@@ -14380,7 +14473,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +{
 +      int err;
 +      loff_t sz;
-+      aufs_bindex_t bstart;
++      aufs_bindex_t bstart, ibstart;
 +      struct dentry *hi_wh, *parent;
 +      struct inode *inode;
 +      struct file *h_file;
@@ -14394,8 +14487,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      if (S_ISDIR(inode->i_mode))
 +              au_fset_wrdir(wr_dir_args.flags, ISDIR);
 +      /* plink or hi_wh() case */
-+      if (bstart != au_ibstart(inode))
-+              wr_dir_args.force_btgt = au_ibstart(inode);
++      ibstart = au_ibstart(inode);
++      if (bstart != ibstart)
++              wr_dir_args.force_btgt = ibstart;
 +      err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
 +      if (unlikely(err < 0))
 +              goto out;
@@ -14460,7 +14554,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      else
 +              a->h_path.dentry = hi_wh; /* do not dget here */
 +
-+ out_unlock:
++out_unlock:
 +      mutex_unlock(&a->h_inode->i_mutex);
 +      au_h_open_post(dentry, bstart, h_file);
 +      a->h_inode = a->h_path.dentry->d_inode;
@@ -14470,12 +14564,12 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      }
 +
 +      au_unpin(&a->pin);
-+ out_parent:
++out_parent:
 +      if (parent) {
 +              di_write_unlock(parent);
 +              dput(parent);
 +      }
-+ out:
++out:
 +      return err;
 +}
 +
@@ -14500,7 +14594,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +
 +      file = NULL;
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++      if (unlikely(err))
++              goto out_kfree;
++
 +      if (ia->ia_valid & ATTR_FILE) {
 +              /* currently ftruncate(2) only */
 +              AuDebugOn(!S_ISREG(inode->i_mode));
@@ -14567,20 +14664,21 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      if (!err)
 +              au_cpup_attr_changeable(inode);
 +
-+ out_unlock:
++out_unlock:
 +      mutex_unlock(&a->h_inode->i_mutex);
 +      au_unpin(&a->pin);
-+ out_dentry:
++out_dentry:
 +      di_write_unlock(dentry);
 +      if (file) {
 +              fi_write_unlock(file);
 +              ia->ia_file = file;
 +              ia->ia_valid |= ATTR_FILE;
 +      }
-+ out_si:
++out_si:
 +      si_read_unlock(sb);
++out_kfree:
 +      kfree(a);
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -14622,7 +14720,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      err = 0;
 +      sb = dentry->d_sb;
 +      inode = dentry->d_inode;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      mnt_flags = au_mntflags(sb);
 +      udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
 +
@@ -14671,9 +14769,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      }
 +      goto out;
 +
-+ out_fill:
++out_fill:
 +      generic_fillattr(inode, st);
-+ out:
++out:
 +      di_read_unlock(dentry, AuLock_IR);
 +      si_read_unlock(sb);
 +      return err;
@@ -14704,7 +14802,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      }
 +      err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -14748,7 +14846,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +      }
 +      __putname(buf.k);
 +
-+ out:
++out:
 +      path_put(&nd->path);
 +      AuTraceErr(err);
 +      return ERR_PTR(err);
@@ -14804,7 +14902,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +};
 diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 --- /usr/share/empty/fs/aufs/i_op_del.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op_del.c   2010-08-21 21:00:02.975972487 +0200
++++ linux/fs/aufs/i_op_del.c   2010-10-01 13:09:26.468878166 +0200
 @@ -0,0 +1,472 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -14890,7 +14988,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +      AuDbg("need_wh %d\n", need_wh);
 +      err = need_wh;
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -14952,7 +15050,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +              err = 0;
 +      dput(h_latest);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -15009,9 +15107,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +      /* returns with the parent is locked and wh_dentry is dget-ed */
 +      goto out; /* success */
 +
-+ out_unpin:
++out_unpin:
 +      au_unpin(pin);
-+ out:
++out:
 +      return wh_dentry;
 +}
 +
@@ -15058,7 +15156,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +              err = 0;
 +      }
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -15176,11 +15274,11 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +                      err = rerr;
 +      }
 +
-+ out_unlock:
++out_unlock:
 +      au_unpin(&pin);
 +      dput(wh_dentry);
 +      dput(h_path.dentry);
-+ out:
++out:
 +      di_write_unlock(parent);
 +      aufs_read_unlock(dentry, AuLock_DW);
 +      return err;
@@ -15264,24 +15362,24 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +                      err = rerr;
 +      }
 +
-+ out_unpin:
++out_unpin:
 +      au_unpin(&pin);
 +      dput(wh_dentry);
 +      dput(h_dentry);
-+ out_args:
++out_args:
 +      di_write_unlock(parent);
 +      if (args)
 +              au_whtmp_rmdir_free(args);
-+ out_unlock:
++out_unlock:
 +      aufs_read_unlock(dentry, AuLock_DW);
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
 diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 --- /usr/share/empty/fs/aufs/i_op_ren.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op_ren.c   2010-08-21 21:00:02.980020464 +0200
-@@ -0,0 +1,977 @@
++++ linux/fs/aufs/i_op_ren.c   2010-10-01 13:09:26.468878166 +0200
+@@ -0,0 +1,980 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -15699,34 +15797,34 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +      err = 0;
 +      goto out_success;
 +
-+ out_diropq:
++out_diropq:
 +      if (au_ftest_ren(a->flags, DIROPQ))
 +              au_ren_rev_diropq(err, a);
-+ out_rename:
++out_rename:
 +      if (!au_ftest_ren(a->flags, CPUP))
 +              au_ren_rev_rename(err, a);
 +      else
 +              au_ren_rev_cpup(err, a);
-+ out_whtmp:
++out_whtmp:
 +      if (a->thargs)
 +              au_ren_rev_whtmp(err, a);
-+ out_whdst:
++out_whdst:
 +      dput(a->dst_wh_dentry);
 +      a->dst_wh_dentry = NULL;
-+ out_whsrc:
++out_whsrc:
 +      if (a->src_wh_dentry)
 +              au_ren_rev_whsrc(err, a);
 +      au_ren_rev_drop(a);
-+ out_success:
++out_success:
 +      dput(a->src_wh_dentry);
 +      dput(a->dst_wh_dentry);
-+ out_thargs:
++out_thargs:
 +      if (a->thargs) {
 +              dput(a->h_dst);
 +              au_whtmp_rmdir_free(a->thargs);
 +              a->thargs = NULL;
 +      }
-+ out:
++out:
 +      return err;
 +}
 +
@@ -15777,7 +15875,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +
 +      err = au_test_empty_lower(dentry);
 +
-+ out:
++out:
 +      if (err == -ENOTEMPTY) {
 +              AuWarn1("renaming dir who has child(ren) on multiple branches,"
 +                      " is not supported\n");
@@ -15822,7 +15920,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +                      a->whlist.nh_num = 0;
 +              }
 +      }
-+ out:
++out:
 +      return err;
 +}
 +
@@ -15872,7 +15970,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +              err = 0;
 +      }
 +
-+ out:
++out:
 +      if (unlikely(err == -ENOENT || err == -EEXIST))
 +              err = -EIO;
 +      AuTraceErr(err);
@@ -15949,9 +16047,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +
 +      err = au_busy_or_stale();
 +
-+ out_unlock:
++out_unlock:
 +      au_ren_unlock(a);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -16120,7 +16218,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
 +              struct inode *_dst_dir, struct dentry *_dst_dentry)
 +{
-+      int err;
++      int err, flags;
 +      /* reduce stack space */
 +      struct au_ren_args *a;
 +
@@ -16148,15 +16246,18 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +      }
 +
 +      err = -ENOTDIR;
++      flags = AuLock_FLUSH | AuLock_NOPLM;
 +      if (S_ISDIR(a->src_inode->i_mode)) {
 +              au_fset_ren(a->flags, ISDIR);
 +              if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
 +                      goto out_free;
-+              aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
-+                                        AuLock_DIR | AuLock_FLUSH);
++              err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++                                              AuLock_DIR | flags);
 +      } else
-+              aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
-+                                        AuLock_FLUSH);
++              err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++                                              flags);
++      if (unlikely(err))
++              goto out_free;
 +
 +      au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
 +      di_write_lock_parent(a->dst_parent);
@@ -16232,13 +16333,13 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +
 +      goto out_hdir; /* success */
 +
-+ out_dt:
++out_dt:
 +      au_ren_rev_dt(err, a);
-+ out_hdir:
++out_hdir:
 +      au_ren_unlock(a);
-+ out_children:
++out_children:
 +      au_nhash_wh_free(&a->whlist);
-+ out_unlock:
++out_unlock:
 +      if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
 +              au_update_dbstart(a->dst_dentry);
 +              d_drop(a->dst_dentry);
@@ -16250,19 +16351,19 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +      else
 +              di_write_unlock2(a->src_parent, a->dst_parent);
 +      aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
-+ out_free:
++out_free:
 +      iput(a->dst_inode);
 +      if (a->thargs)
 +              au_whtmp_rmdir_free(a->thargs);
 +      kfree(a);
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
 diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
 --- /usr/share/empty/fs/aufs/Kconfig   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/Kconfig      2010-08-21 21:00:02.972333781 +0200
-@@ -0,0 +1,175 @@
++++ linux/fs/aufs/Kconfig      2010-10-01 13:09:26.342878167 +0200
+@@ -0,0 +1,182 @@
 +config AUFS_FS
 +      tristate "Aufs (Advanced multi layered unification filesystem) support"
 +      depends on EXPERIMENTAL
@@ -16309,6 +16410,14 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
 +      resources and has a minor impact to performance.
 +endchoice
 +
++config AUFS_SBILIST
++      bool
++      depends on AUFS_MAGIC_SYSRQ || PROC_FS
++      default y
++      help
++      Automatic configuration for internal use.
++      When aufs supports Magic SysRq or /proc, enabled automatically.
++
 +config AUFS_HNOTIFY
 +      bool "Detect direct branch access (bypassing aufs)"
 +      help
@@ -16318,7 +16427,6 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
 +      It will have a negative impact to the performance.
 +      See detail in aufs.5.
 +
-+
 +choice
 +      prompt "method" if AUFS_HNOTIFY
 +      default AUFS_HFSNOTIFY
@@ -16440,7 +16548,7 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
 +endif
 diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
 --- /usr/share/empty/fs/aufs/loop.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/loop.c       2010-08-21 21:00:02.980020464 +0200
++++ linux/fs/aufs/loop.c       2010-10-01 13:09:26.469878166 +0200
 @@ -0,0 +1,63 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -16507,7 +16615,7 @@ diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
 +}
 diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
 --- /usr/share/empty/fs/aufs/loop.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/loop.h       2010-08-21 21:00:02.980020464 +0200
++++ linux/fs/aufs/loop.h       2010-10-01 13:09:26.469878166 +0200
 @@ -0,0 +1,42 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -16553,7 +16661,7 @@ diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
 +#endif /* __AUFS_LOOP_H__ */
 diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
 --- /usr/share/empty/fs/aufs/magic.mk  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/magic.mk     2010-08-21 21:00:02.982333916 +0200
++++ linux/fs/aufs/magic.mk     2010-10-01 13:09:26.469878166 +0200
 @@ -0,0 +1,54 @@
 +
 +# defined in ${srctree}/fs/fuse/inode.c
@@ -16611,8 +16719,8 @@ diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
 +endif
 diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
 --- /usr/share/empty/fs/aufs/Makefile  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/Makefile     2010-08-21 21:00:02.972333781 +0200
-@@ -0,0 +1,38 @@
++++ linux/fs/aufs/Makefile     2010-10-01 13:09:26.342878167 +0200
+@@ -0,0 +1,39 @@
 +
 +include ${src}/magic.mk
 +ifeq (${CONFIG_AUFS_FS},m)
@@ -16629,7 +16737,7 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
 +obj-$(CONFIG_AUFS_FS) += aufs.o
 +aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
 +      wkq.o vfsub.o dcsub.o \
-+      cpup.o whout.o plink.o wbr_policy.o \
++      cpup.o whout.o wbr_policy.o \
 +      dinfo.o dentry.o \
 +      dynop.o \
 +      finfo.o file.o f_op.o \
@@ -16638,6 +16746,7 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
 +      ioctl.o
 +
 +# all are boolean
++aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
 +aufs-$(CONFIG_SYSFS) += sysfs.o
 +aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
 +aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
@@ -16653,8 +16762,8 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
 +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
 diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 --- /usr/share/empty/fs/aufs/module.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/module.c     2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,171 @@
++++ linux/fs/aufs/module.c     2010-10-01 13:09:26.469878166 +0200
+@@ -0,0 +1,182 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -16733,6 +16842,10 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +
 +int au_dir_roflags;
 +
++#ifdef CONFIG_AUFS_SBILIST
++struct au_splhead au_sbilist;
++#endif
++
 +/*
 + * functions for module interface.
 + */
@@ -16773,15 +16886,19 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +
 +      au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
 +
++      au_sbilist_init();
 +      sysaufs_brs_init();
 +      au_debug_init();
 +      au_dy_init();
 +      err = sysaufs_init();
 +      if (unlikely(err))
 +              goto out;
-+      err = au_wkq_init();
++      err = au_procfs_init();
 +      if (unlikely(err))
 +              goto out_sysaufs;
++      err = au_wkq_init();
++      if (unlikely(err))
++              goto out_procfs;
 +      err = au_hnotify_init();
 +      if (unlikely(err))
 +              goto out_wkq;
@@ -16798,18 +16915,20 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +      printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
 +      goto out; /* success */
 +
-+ out_cache:
++out_cache:
 +      au_cache_fin();
-+ out_sysrq:
++out_sysrq:
 +      au_sysrq_fin();
-+ out_hin:
++out_hin:
 +      au_hnotify_fin();
-+ out_wkq:
++out_wkq:
 +      au_wkq_fin();
-+ out_sysaufs:
++out_procfs:
++      au_procfs_fin();
++out_sysaufs:
 +      sysaufs_fin();
 +      au_dy_fin();
-+ out:
++out:
 +      return err;
 +}
 +
@@ -16820,6 +16939,7 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +      au_sysrq_fin();
 +      au_hnotify_fin();
 +      au_wkq_fin();
++      au_procfs_fin();
 +      sysaufs_fin();
 +      au_dy_fin();
 +}
@@ -16828,8 +16948,8 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +module_exit(aufs_exit);
 diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
 --- /usr/share/empty/fs/aufs/module.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/module.h     2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,82 @@
++++ linux/fs/aufs/module.h     2010-10-01 13:09:26.469878166 +0200
+@@ -0,0 +1,91 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -16872,9 +16992,18 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
 +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
 +int au_seq_path(struct seq_file *seq, struct path *path);
 +
-+/* ---------------------------------------------------------------------- */
-+
-+/* kmem cache */
++#ifdef CONFIG_PROC_FS
++/* procfs.c */
++int __init au_procfs_init(void);
++void au_procfs_fin(void);
++#else
++AuStubInt0(au_procfs_init, void);
++AuStubVoid(au_procfs_fin, void);
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++/* kmem cache */
 +enum {
 +      AuCache_DINFO,
 +      AuCache_ICNTNR,
@@ -16914,7 +17043,7 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
 +#endif /* __AUFS_MODULE_H__ */
 diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
 --- /usr/share/empty/fs/aufs/mtx.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/mtx.h        2010-08-21 21:00:02.982333916 +0200
++++ linux/fs/aufs/mtx.h        2010-10-01 13:09:26.469878166 +0200
 @@ -0,0 +1,48 @@
 +/*
 + * Copyright (C) 2010 Junjiro R. Okajima
@@ -16966,8 +17095,8 @@ diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
 +#endif /* __AUFS_MTX_H__ */
 diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 --- /usr/share/empty/fs/aufs/opts.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/opts.c       2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,1585 @@
++++ linux/fs/aufs/opts.c       2010-10-01 13:09:26.470878166 +0200
+@@ -0,0 +1,1595 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -16991,6 +17120,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 + */
 +
 +#include <linux/file.h>
++#include <linux/jiffies.h>
 +#include <linux/namei.h>
 +#include <linux/types.h> /* a distribution requires */
 +#include <linux/parser.h>
@@ -17056,8 +17186,14 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      {Opt_trunc_xib, "trunc_xib"},
 +      {Opt_notrunc_xib, "notrunc_xib"},
 +
++#ifdef CONFIG_PROC_FS
 +      {Opt_plink, "plink"},
++#else
++      {Opt_ignore_silent, "plink"},
++#endif
++
 +      {Opt_noplink, "noplink"},
++
 +#ifdef CONFIG_AUFS_DEBUG
 +      {Opt_list_plink, "list_plink"},
 +#endif
@@ -17276,7 +17412,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      int n, err;
 +
 +      err = 0;
-+      if (!match_int(arg, &n) && 0 <= n)
++      if (!match_int(arg, &n) && 0 <= n && n <= MAX_SEC_IN_JIFFIES)
 +              create->mfs_second = n;
 +      else {
 +              pr_err("bad integer in %s\n", str);
@@ -17597,7 +17733,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      pr_err("lookup failed %s (%d)\n", add->pathname, err);
 +      err = -EINVAL;
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -17634,7 +17770,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      del->h_path.dentry = dget(au_h_dptr(root, bindex));
 +      del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
 +
-+ out:
++out:
 +      aufs_read_unlock(root, !AuLock_IR);
 +      return err;
 +}
@@ -17667,7 +17803,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      mod->h_root = dget(path.dentry);
 +      path_put(&path);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -17692,7 +17828,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +            mod->path, mod->perm, args[1].from);
 +      mod->h_root = dget(au_h_dptr(root, bindex));
 +
-+ out:
++out:
 +      aufs_read_unlock(root, !AuLock_IR);
 +      return err;
 +}
@@ -17720,7 +17856,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      xino->file = file;
 +      xino->path = args[0].from;
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -17758,7 +17894,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +              err = -EINVAL;
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -17906,7 +18042,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +                      break;
 +
 +              case Opt_rdcache:
-+                      if (unlikely(match_int(&a->args[0], &opt->rdcache)))
++                      if (unlikely(match_int(&a->args[0], &opt->rdcache)
++                                   || opt->rdcache > MAX_SEC_IN_JIFFIES))
 +                              break;
 +                      err = 0;
 +                      opt->type = token;
@@ -18025,7 +18162,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      if (unlikely(err))
 +              au_opts_free(opts);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -18056,7 +18193,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +      case AuWbrCreate_MFSV:
 +      case AuWbrCreate_PMFS:
 +      case AuWbrCreate_PMFSV:
-+              sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
++              sbinfo->si_wbr_mfs.mfs_expire
++                      = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
 +              break;
 +      }
 +
@@ -18093,7 +18231,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +              break;
 +      case Opt_noplink:
 +              if (au_opt_test(sbinfo->si_mntflags, PLINK))
-+                      au_plink_put(sb);
++                      au_plink_put(sb, /*verbose*/1);
 +              au_opt_clr(sbinfo->si_mntflags, PLINK);
 +              break;
 +      case Opt_list_plink:
@@ -18162,7 +18300,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +              break;
 +
 +      case Opt_rdcache:
-+              sbinfo->si_rdcache = opt->rdcache * HZ;
++              sbinfo->si_rdcache
++                      = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
 +              break;
 +      case Opt_rdblk:
 +              sbinfo->si_rdblk = opt->rdblk;
@@ -18496,7 +18635,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +              au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -18555,8 +18694,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +}
 diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
 --- /usr/share/empty/fs/aufs/opts.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/opts.h       2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,198 @@
++++ linux/fs/aufs/opts.h       2010-10-01 13:09:26.470878166 +0200
+@@ -0,0 +1,207 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -18639,6 +18778,15 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
 +} while (0)
 +#define au_opt_clr(flags, name)               { ((flags) &= ~AuOpt_##name); }
 +
++static inline unsigned int au_opts_plink(unsigned int mntflags)
++{
++#ifdef CONFIG_PROC_FS
++      return mntflags;
++#else
++      return mntflags & ~AuOpt_PLINK;
++#endif
++}
++
 +/* ---------------------------------------------------------------------- */
 +
 +/* policies to select one among multiple writable branches */
@@ -18757,8 +18905,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
 +#endif /* __AUFS_OPTS_H__ */
 diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 --- /usr/share/empty/fs/aufs/plink.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/plink.c      2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,451 @@
++++ linux/fs/aufs/plink.c      2010-10-01 13:09:26.470878166 +0200
+@@ -0,0 +1,483 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -18784,53 +18932,102 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +#include "aufs.h"
 +
 +/*
++ * the pseudo-link maintenance mode.
 + * during a user process maintains the pseudo-links,
 + * prohibit adding a new plink and branch manipulation.
++ *
++ * Flags
++ * NOPLM:
++ *    For entry functions which will handle plink, and i_mutex is already held
++ *    in VFS.
++ *    They cannot wait and should return an error at once.
++ *    Callers has to check the error.
++ * NOPLMW:
++ *    For entry functions which will handle plink, but i_mutex is not held
++ *    in VFS.
++ *    They can wait the plink maintenance mode to finish.
++ *
++ * They behave like F_SETLK and F_SETLKW.
++ * If the caller never handle plink, then both flags are unnecessary.
 + */
-+void au_plink_maint_block(struct super_block *sb)
++
++int au_plink_maint(struct super_block *sb, int flags)
 +{
-+      struct au_sbinfo *sbi = au_sbi(sb);
++      int err;
++      pid_t pid, ppid;
++      struct au_sbinfo *sbi;
 +
 +      SiMustAnyLock(sb);
 +
-+      /* gave up wake_up_bit() */
-+      wait_event(sbi->si_plink_wq, !sbi->si_plink_maint);
++      err = 0;
++      if (!au_opt_test(au_mntflags(sb), PLINK))
++              goto out;
++
++      sbi = au_sbi(sb);
++      pid = sbi->si_plink_maint_pid;
++      if (!pid || pid == current->pid)
++              goto out;
++
++      /* todo: it highly depends upon /sbin/mount.aufs */
++      rcu_read_lock();
++      ppid = task_pid_vnr(rcu_dereference(current->real_parent));
++      rcu_read_unlock();
++      if (pid == ppid)
++              goto out;
++
++      if (au_ftest_lock(flags, NOPLMW)) {
++              /*
++               * todo: debug by lockdep, if there is no i_mutex lock in VFS,
++               * we don't need to wait.
++               */
++              while (sbi->si_plink_maint_pid) {
++                      si_read_unlock(sb);
++                      /* gave up wake_up_bit() */
++                      wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
++
++                      if (au_ftest_lock(flags, FLUSH))
++                              au_nwt_flush(&sbi->si_nowait);
++                      si_noflush_read_lock(sb);
++              }
++      } else if (au_ftest_lock(flags, NOPLM)) {
++              AuDbg("ppid %d, pid %d\n", ppid, pid);
++              err = -EAGAIN;
++      }
++
++out:
++      return err;
 +}
 +
-+void au_plink_maint_leave(struct file *file)
++void au_plink_maint_leave(struct au_sbinfo *sbinfo)
 +{
-+      struct au_sbinfo *sbinfo;
 +      int iam;
 +
-+      AuDebugOn(atomic_long_read(&file->f_count));
-+
-+      sbinfo = au_sbi(file->f_dentry->d_sb);
 +      spin_lock(&sbinfo->si_plink_maint_lock);
-+      iam = (sbinfo->si_plink_maint == file);
++      iam = (sbinfo->si_plink_maint_pid == current->pid);
 +      if (iam)
-+              sbinfo->si_plink_maint = NULL;
++              sbinfo->si_plink_maint_pid = 0;
 +      spin_unlock(&sbinfo->si_plink_maint_lock);
 +      if (iam)
 +              wake_up_all(&sbinfo->si_plink_wq);
 +}
 +
-+static int au_plink_maint_enter(struct file *file)
++int au_plink_maint_enter(struct super_block *sb)
 +{
 +      int err;
-+      struct super_block *sb;
 +      struct au_sbinfo *sbinfo;
 +
 +      err = 0;
-+      sb = file->f_dentry->d_sb;
 +      sbinfo = au_sbi(sb);
 +      /* make sure i am the only one in this fs */
-+      si_write_lock(sb);
-+      /* spin_lock(&sbinfo->si_plink_maint_lock); */
-+      if (!sbinfo->si_plink_maint)
-+              sbinfo->si_plink_maint = file;
-+      else
-+              err = -EBUSY;
-+      /* spin_unlock(&sbinfo->si_plink_maint_lock); */
++      si_write_lock(sb, AuLock_FLUSH);
++      if (au_opt_test(au_mntflags(sb), PLINK)) {
++              spin_lock(&sbinfo->si_plink_maint_lock);
++              if (!sbinfo->si_plink_maint_pid)
++                      sbinfo->si_plink_maint_pid = current->pid;
++              else
++                      err = -EBUSY;
++              spin_unlock(&sbinfo->si_plink_maint_lock);
++      }
 +      si_write_unlock(sb);
 +
 +      return err;
@@ -18857,6 +19054,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +
 +      sbinfo = au_sbi(sb);
 +      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++      AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
 +
 +      plink_list = &sbinfo->si_plink.head;
 +      rcu_read_lock();
@@ -18877,6 +19075,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +      sbinfo = au_sbi(inode->i_sb);
 +      AuRwMustAnyLock(&sbinfo->si_rwsem);
 +      AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
++      AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
 +
 +      found = 0;
 +      plink_list = &sbinfo->si_plink.head;
@@ -18921,6 +19120,8 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +              .name   = a
 +      };
 +
++      AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
++
 +      br = au_sbr(inode->i_sb, bindex);
 +      h_parent = br->br_wbr->wbr_plink;
 +      h_dir = h_parent->d_inode;
@@ -18944,7 +19145,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +      struct inode *h_dir;
 +
 +      h_dir = h_parent->d_inode;
-+ again:
++again:
 +      h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
 +      err = PTR_ERR(h_path.dentry);
 +      if (IS_ERR(h_path.dentry))
@@ -18964,7 +19165,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +              err = vfsub_link(h_dentry, h_dir, &h_path);
 +      dput(h_path.dentry);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -19053,6 +19254,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +      sb = inode->i_sb;
 +      sbinfo = au_sbi(sb);
 +      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++      AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
 +
 +      cnt = 0;
 +      found = 0;
@@ -19091,7 +19293,6 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +              cnt++;
 +              WARN_ONCE(cnt > AUFS_PLINK_WARN,
 +                        "unexpectedly many pseudo links, %d\n", cnt);
-+              au_plink_maint_block(sb);
 +              err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
 +      } else {
 +              do_put_plink(tmp, 0);
@@ -19109,7 +19310,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +}
 +
 +/* free all plinks */
-+void au_plink_put(struct super_block *sb)
++void au_plink_put(struct super_block *sb, int verbose)
 +{
 +      struct au_sbinfo *sbinfo;
 +      struct list_head *plink_list;
@@ -19119,14 +19320,27 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +
 +      sbinfo = au_sbi(sb);
 +      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++      AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
 +
 +      plink_list = &sbinfo->si_plink.head;
 +      /* no spin_lock since sbinfo is write-locked */
++      WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
 +      list_for_each_entry_safe(plink, tmp, plink_list, list)
 +              do_put_plink(plink, 0);
 +      INIT_LIST_HEAD(plink_list);
 +}
 +
++void au_plink_clean(struct super_block *sb, int verbose)
++{
++      struct dentry *root;
++
++      root = sb->s_root;
++      aufs_write_lock(root);
++      if (au_opt_test(au_mntflags(sb), PLINK))
++              au_plink_put(sb, verbose);
++      aufs_write_unlock(root);
++}
++
 +/* free the plinks on a branch specified by @br_id */
 +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
 +{
@@ -19141,6 +19355,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +
 +      sbinfo = au_sbi(sb);
 +      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++      AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
 +
 +      plink_list = &sbinfo->si_plink.head;
 +      /* no spin_lock since sbinfo is write-locked */
@@ -19175,44 +19390,9 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +              iput(inode);
 +      }
 +}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+long au_plink_ioctl(struct file *file, unsigned int cmd)
-+{
-+      long err;
-+      struct super_block *sb;
-+
-+      err = -EACCES;
-+      if (!capable(CAP_SYS_ADMIN))
-+              goto out;
-+
-+      err = 0;
-+      sb = file->f_dentry->d_sb;
-+      switch (cmd) {
-+      case AUFS_CTL_PLINK_MAINT:
-+              /*
-+               * pseudo-link maintenance mode,
-+               * cleared by aufs_release_dir()
-+               */
-+              err = au_plink_maint_enter(file);
-+              break;
-+      case AUFS_CTL_PLINK_CLEAN:
-+              aufs_write_lock(sb->s_root);
-+              if (au_opt_test(au_mntflags(sb), PLINK))
-+                      au_plink_put(sb);
-+              aufs_write_unlock(sb->s_root);
-+              break;
-+      default:
-+              /* err = -ENOTTY; */
-+              err = -EINVAL;
-+      }
-+ out:
-+      return err;
-+}
 diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
 --- /usr/share/empty/fs/aufs/poll.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/poll.c       2010-08-21 21:00:02.982333916 +0200
++++ linux/fs/aufs/poll.c       2010-10-01 13:09:26.488878162 +0200
 @@ -0,0 +1,56 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -19251,7 +19431,7 @@ diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
 +      mask = POLLERR /* | POLLIN | POLLOUT */;
 +      dentry = file->f_dentry;
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
 +      if (unlikely(err))
 +              goto out;
@@ -19265,15 +19445,188 @@ diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_read_unlock(file);
 +
-+ out:
++out:
 +      si_read_unlock(sb);
 +      AuTraceErr((int)mask);
 +      return mask;
 +}
+diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
+--- /usr/share/empty/fs/aufs/procfs.c  1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/procfs.c     2010-10-01 13:09:26.488878162 +0200
+@@ -0,0 +1,169 @@
++/*
++ * Copyright (C) 2010 Junjiro R. Okajima
++ *
++ * This program, aufs is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ */
++
++/*
++ * procfs interfaces
++ */
++
++#include <linux/proc_fs.h>
++#include "aufs.h"
++
++static int au_procfs_plm_release(struct inode *inode, struct file *file)
++{
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = file->private_data;
++      if (sbinfo) {
++              au_plink_maint_leave(sbinfo);
++              kobject_put(&sbinfo->si_kobj);
++      }
++
++      return 0;
++}
++
++static void au_procfs_plm_write_clean(struct file *file)
++{
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = file->private_data;
++      if (sbinfo)
++              au_plink_clean(sbinfo->si_sb, /*verbose*/0);
++}
++
++static int au_procfs_plm_write_si(struct file *file, unsigned long id)
++{
++      int err;
++      struct super_block *sb;
++      struct au_sbinfo *sbinfo;
++
++      err = -EBUSY;
++      if (unlikely(file->private_data))
++              goto out;
++
++      sb = NULL;
++      spin_lock(&au_sbilist.spin);
++      list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
++              if (id == sysaufs_si_id(sbinfo)) {
++                      kobject_get(&sbinfo->si_kobj);
++                      sb = sbinfo->si_sb;
++                      break;
++              }
++      spin_unlock(&au_sbilist.spin);
++
++      err = -EINVAL;
++      if (unlikely(!sb))
++              goto out;
++
++      err = au_plink_maint_enter(sb);
++      if (!err)
++              /* keep kobject_get() */
++              file->private_data = sbinfo;
++      else
++              kobject_put(&sbinfo->si_kobj);
++out:
++      return err;
++}
++
++/*
++ * Accept a valid "si=xxxx" only.
++ * Once it is accepted successfully, accept "clean" too.
++ */
++static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
++                                 size_t count, loff_t *ppos)
++{
++      ssize_t err;
++      unsigned long id;
++      /* last newline is allowed */
++      char buf[3 + sizeof(unsigned long) * 2 + 1];
++
++      err = -EACCES;
++      if (unlikely(!capable(CAP_SYS_ADMIN)))
++              goto out;
++
++      err = -EINVAL;
++      if (unlikely(count > sizeof(buf)))
++              goto out;
++
++      err = copy_from_user(buf, ubuf, count);
++      if (unlikely(err)) {
++              err = -EFAULT;
++              goto out;
++      }
++      buf[count] = 0;
++
++      err = -EINVAL;
++      if (!strcmp("clean", buf)) {
++              au_procfs_plm_write_clean(file);
++              goto out_success;
++      } else if (unlikely(strncmp("si=", buf, 3)))
++              goto out;
++
++      err = strict_strtoul(buf + 3, 16, &id);
++      if (unlikely(err))
++              goto out;
++
++      err = au_procfs_plm_write_si(file, id);
++      if (unlikely(err))
++              goto out;
++
++out_success:
++      err = count; /* success */
++out:
++      return err;
++}
++
++static const struct file_operations au_procfs_plm_fop = {
++      .write          = au_procfs_plm_write,
++      .release        = au_procfs_plm_release,
++      .owner          = THIS_MODULE
++};
++
++/* ---------------------------------------------------------------------- */
++
++static struct proc_dir_entry *au_procfs_dir;
++
++void au_procfs_fin(void)
++{
++      remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
++      remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
++}
++
++int __init au_procfs_init(void)
++{
++      int err;
++      struct proc_dir_entry *entry;
++
++      err = -ENOMEM;
++      au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
++      if (unlikely(!au_procfs_dir))
++              goto out;
++
++      entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
++                          au_procfs_dir, &au_procfs_plm_fop);
++      if (unlikely(!entry))
++              goto out_dir;
++
++      err = 0;
++      goto out; /* success */
++
++
++out_dir:
++      remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
++out:
++      return err;
++}
 diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
 --- /usr/share/empty/fs/aufs/rdu.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/rdu.c        2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,377 @@
++++ linux/fs/aufs/rdu.c        2010-10-01 13:09:26.489878162 +0200
+@@ -0,0 +1,380 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -19359,7 +19712,7 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
 +              rdu->tail = arg->ent;
 +      }
 +
-+ out:
++out:
 +      /* AuTraceErr(err); */
 +      return err;
 +}
@@ -19388,7 +19741,7 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
 +               && !au_ftest_rdu(cookie->flags, FULL));
 +      cookie->h_pos = h_file->f_pos;
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -19441,7 +19794,10 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
 +              goto out_mtx;
 +
 +      arg.sb = inode->i_sb;
-+      si_read_lock(arg.sb, AuLock_FLUSH);
++      err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
++      if (unlikely(err))
++              goto out_mtx;
++      /* todo: reval? */
 +      fi_read_lock(file);
 +
 +      err = -EAGAIN;
@@ -19484,12 +19840,12 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
 +      fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
 +      ii_read_unlock(inode);
 +
-+ out_unlock:
++out_unlock:
 +      fi_read_unlock(file);
 +      si_read_unlock(arg.sb);
-+ out_mtx:
++out_mtx:
 +      mutex_unlock(&inode->i_mutex);
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -19599,7 +19955,7 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
 +              err = -EINVAL;
 +      }
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -19646,15 +20002,15 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
 +              err = -EINVAL;
 +      }
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
 +#endif
 diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
 --- /usr/share/empty/fs/aufs/rwsem.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/rwsem.h      2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,187 @@
++++ linux/fs/aufs/rwsem.h      2010-10-01 13:09:26.489878162 +0200
+@@ -0,0 +1,189 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -19700,9 +20056,9 @@ diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
 +      smp_mb(); /* atomic set */ \
 +} while (0)
 +
-+#define AuDbgRcntInc(rw)      atomic_inc_return(&(rw)->rcnt)
++#define AuDbgRcntInc(rw)      atomic_inc(&(rw)->rcnt)
 +#define AuDbgRcntDec(rw)      WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
-+#define AuDbgWcntInc(rw)      WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
++#define AuDbgWcntInc(rw)      atomic_inc(&(rw)->wcnt)
 +#define AuDbgWcntDec(rw)      WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
 +#else
 +#define AuDbgCntInit(rw)      do {} while (0)
@@ -19722,6 +20078,8 @@ diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
 +#define AuRwDestroy(rw)               AuDebugOn(atomic_read(&(rw)->rcnt) \
 +                                      || atomic_read(&(rw)->wcnt))
 +
++#define au_rw_class(rw, key)  lockdep_set_class(&(rw)->rwsem, key)
++
 +static inline void au_rw_init(struct au_rwsem *rw)
 +{
 +      AuDbgCntInit(rw);
@@ -19844,8 +20202,8 @@ diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
 +#endif /* __AUFS_RWSEM_H__ */
 diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 --- /usr/share/empty/fs/aufs/sbinfo.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sbinfo.c     2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,269 @@
++++ linux/fs/aufs/sbinfo.c     2010-10-01 13:09:26.489878162 +0200
+@@ -0,0 +1,311 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -19868,6 +20226,7 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 + * superblock private data
 + */
 +
++#include <linux/jiffies.h>
 +#include "aufs.h"
 +
 +/*
@@ -19876,18 +20235,15 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +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));
-+      AuDebugOn(sbinfo->si_plink_maint);
++      AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
 +
-+      sb = sbinfo->si_sb;
-+      si_write_lock(sb);
-+      au_xino_clr(sb);
++      au_rw_write_lock(&sbinfo->si_rwsem);
 +      au_br_free(sbinfo);
-+      si_write_unlock(sb);
++      au_rw_write_unlock(&sbinfo->si_rwsem);
 +
 +      AuDebugOn(radix_tree_gang_lookup
 +                (&sbinfo->au_si_pid.tree, (void **)&locked,
@@ -19906,6 +20262,7 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +{
 +      int err;
 +      struct au_sbinfo *sbinfo;
++      static struct lock_class_key aufs_si;
 +
 +      err = -ENOMEM;
 +      sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
@@ -19931,6 +20288,7 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +
 +      au_nwt_init(&sbinfo->si_nowait);
 +      au_rw_init_wlock(&sbinfo->si_rwsem);
++      au_rw_class(&sbinfo->si_rwsem, &aufs_si);
 +      spin_lock_init(&sbinfo->au_si_pid.tree_lock);
 +      INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
 +
@@ -19941,13 +20299,13 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +      sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
 +      sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
 +
-+      sbinfo->si_mntflags = AuOpt_Def;
++      sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
 +
 +      mutex_init(&sbinfo->si_xib_mtx);
 +      sbinfo->si_xino_brid = -1;
 +      /* leave si_xib_last_pindex and si_xib_next_bit */
 +
-+      sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
++      sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
 +      sbinfo->si_rdblk = AUFS_RDBLK_DEF;
 +      sbinfo->si_rdhash = AUFS_RDHASH_DEF;
 +      sbinfo->si_dirwh = AUFS_DIRWH_DEF;
@@ -19963,13 +20321,13 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +      au_debug_sbinfo_init(sbinfo);
 +      return 0; /* success */
 +
-+ out_br:
++out_br:
 +      kfree(sbinfo->si_branch);
-+ out_pidmap:
++out_pidmap:
 +      kfree(sbinfo->au_si_pid.bitmap);
-+ out_sbinfo:
++out_sbinfo:
 +      kfree(sbinfo);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -20028,14 +20386,52 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +
 +/* ---------------------------------------------------------------------- */
 +
++/* it is ok that new 'nwt' tasks are appended while we are sleeping */
++int si_read_lock(struct super_block *sb, int flags)
++{
++      int err;
++
++      err = 0;
++      if (au_ftest_lock(flags, FLUSH))
++              au_nwt_flush(&au_sbi(sb)->si_nowait);
++
++      si_noflush_read_lock(sb);
++      err = au_plink_maint(sb, flags);
++      if (unlikely(err))
++              si_read_unlock(sb);
++
++      return err;
++}
++
++int si_write_lock(struct super_block *sb, int flags)
++{
++      int err;
++
++      if (au_ftest_lock(flags, FLUSH))
++              au_nwt_flush(&au_sbi(sb)->si_nowait);
++
++      si_noflush_write_lock(sb);
++      err = au_plink_maint(sb, flags);
++      if (unlikely(err))
++              si_write_unlock(sb);
++
++      return err;
++}
++
 +/* dentry and super_block lock. call at entry point */
-+void aufs_read_lock(struct dentry *dentry, int flags)
++int aufs_read_lock(struct dentry *dentry, int flags)
 +{
-+      si_read_lock(dentry->d_sb, flags);
-+      if (au_ftest_lock(flags, DW))
-+              di_write_lock_child(dentry);
-+      else
-+              di_read_lock_child(dentry, flags);
++      int err;
++
++      err = si_read_lock(dentry->d_sb, flags);
++      if (!err) {
++              if (au_ftest_lock(flags, DW))
++                      di_write_lock_child(dentry);
++              else
++                      di_read_lock_child(dentry, flags);
++      }
++
++      return err;
 +}
 +
 +void aufs_read_unlock(struct dentry *dentry, int flags)
@@ -20049,7 +20445,7 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +
 +void aufs_write_lock(struct dentry *dentry)
 +{
-+      si_write_lock(dentry->d_sb);
++      si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
 +      di_write_lock_child(dentry);
 +}
 +
@@ -20059,10 +20455,14 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +      si_write_unlock(dentry->d_sb);
 +}
 +
-+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
++int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
 +{
-+      si_read_lock(d1->d_sb, flags);
-+      di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
++      int err;
++
++      err = si_read_lock(d1->d_sb, flags);
++      if (!err)
++              di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
++      return err;
 +}
 +
 +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
@@ -20117,7 +20517,7 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +}
 diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
 --- /usr/share/empty/fs/aufs/spl.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/spl.h        2010-08-21 21:00:02.982333916 +0200
++++ linux/fs/aufs/spl.h        2010-10-01 13:09:26.489878162 +0200
 @@ -0,0 +1,66 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -20187,8 +20587,8 @@ diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
 +#endif /* __AUFS_SPL_H__ */
 diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 --- /usr/share/empty/fs/aufs/super.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/super.c      2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,848 @@
++++ linux/fs/aufs/super.c      2010-10-01 13:09:26.489878162 +0200
+@@ -0,0 +1,863 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -20212,6 +20612,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 + */
 +
 +#include <linux/buffer_head.h>
++#include <linux/jiffies.h>
 +#include <linux/module.h>
 +#include <linux/seq_file.h>
 +#include <linux/statfs.h>
@@ -20262,7 +20663,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +              inode = ERR_PTR(err);
 +      }
 +
-+ out:
++out:
 +      /* never return NULL */
 +      AuDebugOn(!inode);
 +      AuTraceErrPtr(inode);
@@ -20314,11 +20715,13 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +              break;
 +      case AuWbrCreate_MFSV:
 +              seq_printf(m, /*pat*/"mfs:%lu",
-+                         sbinfo->si_wbr_mfs.mfs_expire / HZ);
++                         jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
++                         / MSEC_PER_SEC);
 +              break;
 +      case AuWbrCreate_PMFSV:
 +              seq_printf(m, /*pat*/"pmfs:%lu",
-+                         sbinfo->si_wbr_mfs.mfs_expire / HZ);
++                         jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
++                         / MSEC_PER_SEC);
 +              break;
 +      case AuWbrCreate_MFSRR:
 +              seq_printf(m, /*pat*/"mfsrr:%llu",
@@ -20327,7 +20730,8 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      case AuWbrCreate_MFSRRV:
 +              seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
 +                         sbinfo->si_wbr_mfs.mfsrr_watermark,
-+                         sbinfo->si_wbr_mfs.mfs_expire / HZ);
++                         jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
++                         / MSEC_PER_SEC);
 +              break;
 +      }
 +}
@@ -20373,7 +20777,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      seq_puts(seq, ",xino=");
 +      err = au_xino_path(seq, f);
 +
-+ out:
++out:
 +      return err;
 +#endif
 +}
@@ -20439,7 +20843,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +
 +      AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
 +
-+      n = sbinfo->si_rdcache / HZ;
++      n = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
 +      AuUInt(RDCACHE, rdcache, n);
 +
 +      AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
@@ -20450,7 +20854,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      AuBool(WARN_PERM, warn_perm);
 +      AuBool(VERBOSE, verbose);
 +
-+ out:
++out:
 +      /* be sure to print "br:" last */
 +      if (!sysaufs_brs) {
 +              seq_puts(m, ",br:");
@@ -20523,7 +20927,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      buf->f_files = files;
 +      buf->f_ffree = ffree;
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -20554,26 +20958,6 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +
 +/* ---------------------------------------------------------------------- */
 +
-+/*
-+ * this IS NOT for super_operations.
-+ * I guess it will be reverted someday.
-+ */
-+static void aufs_umount_begin(struct super_block *sb)
-+{
-+      struct au_sbinfo *sbinfo;
-+
-+      sbinfo = au_sbi(sb);
-+      if (!sbinfo)
-+              return;
-+
-+      si_write_lock(sb);
-+      if (au_opt_test(au_mntflags(sb), PLINK))
-+              au_plink_put(sb);
-+      if (sbinfo->si_wbr_create_ops->fin)
-+              sbinfo->si_wbr_create_ops->fin(sb);
-+      si_write_unlock(sb);
-+}
-+
 +/* final actions when unmounting a file system */
 +static void aufs_put_super(struct super_block *sb)
 +{
@@ -20583,7 +20967,6 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      if (!sbinfo)
 +              return;
 +
-+      aufs_umount_begin(sb);
 +      dbgaufs_si_fin(sbinfo);
 +      kobject_put(&sbinfo->si_kobj);
 +}
@@ -20682,9 +21065,9 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +              }
 +      }
 +
-+ out_dpages:
++out_dpages:
 +      au_dpages_free(&dpages);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -20752,9 +21135,9 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +              }
 +      }
 +
-+ out_dpages:
++out_dpages:
 +      au_dpages_free(&dpages);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -20824,9 +21207,12 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      err = 0;
 +      root = sb->s_root;
 +      if (!data || !*data) {
-+              aufs_write_lock(root);
-+              err = au_opts_verify(sb, *flags, /*pending*/0);
-+              aufs_write_unlock(root);
++              err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++              if (!err) {
++                      di_write_lock_child(root);
++                      err = au_opts_verify(sb, *flags, /*pending*/0);
++                      aufs_write_unlock(root);
++              }
 +              goto out;
 +      }
 +
@@ -20847,7 +21233,10 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      sbinfo = au_sbi(sb);
 +      inode = root->d_inode;
 +      mutex_lock(&inode->i_mutex);
-+      aufs_write_lock(root);
++      err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++      if (unlikely(err))
++              goto out_mtx;
++      di_write_lock_child(root);
 +
 +      /* au_opts_remount() may return an error */
 +      err = au_opts_remount(sb, &opts);
@@ -20864,11 +21253,12 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      }
 +
 +      aufs_write_unlock(root);
-+      mutex_unlock(&inode->i_mutex);
 +
-+ out_opts:
++out_mtx:
++      mutex_unlock(&inode->i_mutex);
++out_opts:
 +      free_page((unsigned long)opts.opt);
-+ out:
++out:
 +      err = cvt_err(err);
 +      AuTraceErr(err);
 +      return err;
@@ -20920,10 +21310,9 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      dput(root);
 +      goto out; /* do not iput */
 +
-+ out_iput:
++out_iput:
 +      iget_failed(inode);
-+      iput(inode);
-+ out:
++out:
 +      return err;
 +
 +}
@@ -20991,15 +21380,15 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      if (!err)
 +              goto out_opts; /* success */
 +
-+ out_root:
++out_root:
 +      dput(root);
 +      sb->s_root = NULL;
-+ out_info:
++out_info:
 +      kobject_put(&au_sbi(sb)->si_kobj);
 +      sb->s_fs_info = NULL;
-+ out_opts:
++out_opts:
 +      free_page((unsigned long)opts.opt);
-+ out:
++out:
 +      AuTraceErr(err);
 +      err = cvt_err(err);
 +      AuTraceErr(err);
@@ -21020,27 +21409,53 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +      err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
 +      if (!err) {
 +              sb = mnt->mnt_sb;
-+              si_write_lock(sb);
++              si_write_lock(sb, !AuLock_FLUSH);
 +              sysaufs_brs_add(sb, 0);
 +              si_write_unlock(sb);
++              au_sbilist_add(sb);
 +      }
 +      return err;
 +}
 +
++static void aufs_kill_sb(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = au_sbi(sb);
++      if (sbinfo) {
++              au_sbilist_del(sb);
++              aufs_write_lock(sb->s_root);
++              if (sbinfo->si_wbr_create_ops->fin)
++                      sbinfo->si_wbr_create_ops->fin(sb);
++              if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
++                      au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
++                      au_remount_refresh(sb, /*flags*/0);
++              }
++              if (au_opt_test(sbinfo->si_mntflags, PLINK))
++                      au_plink_put(sb, /*verbose*/1);
++              au_xino_clr(sb);
++              aufs_write_unlock(sb->s_root);
++
++              au_plink_maint_leave(sbinfo);
++              au_nwt_flush(&sbinfo->si_nowait);
++      }
++      generic_shutdown_super(sb);
++}
++
 +struct file_system_type aufs_fs_type = {
 +      .name           = AUFS_FSTYPE,
 +      .fs_flags       =
 +              FS_RENAME_DOES_D_MOVE   /* a race between rename and others */
 +              | FS_REVAL_DOT,         /* for NFS branch and udba */
 +      .get_sb         = aufs_get_sb,
-+      .kill_sb        = generic_shutdown_super,
++      .kill_sb        = aufs_kill_sb,
 +      /* no need to __module_get() and module_put(). */
 +      .owner          = THIS_MODULE,
 +};
 diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 --- /usr/share/empty/fs/aufs/super.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/super.h      2010-08-21 21:00:02.982333916 +0200
-@@ -0,0 +1,465 @@
++++ linux/fs/aufs/super.h      2010-10-01 13:09:26.489878162 +0200
+@@ -0,0 +1,488 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -21162,7 +21577,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +#endif
 +
 +      /* vdir parameters */
-+      unsigned long           si_rdcache;     /* max cache time in HZ */
++      unsigned long           si_rdcache;     /* max cache time in jiffies */
 +      unsigned int            si_rdblk;       /* deblk size */
 +      unsigned int            si_rdhash;      /* hash size */
 +
@@ -21184,7 +21599,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +      struct au_splhead       si_plink;
 +      wait_queue_head_t       si_plink_wq;
 +      spinlock_t              si_plink_maint_lock;
-+      struct file             *si_plink_maint;
++      pid_t                   si_plink_maint_pid;
 +
 +      /*
 +       * sysfs and lifetime management.
@@ -21200,6 +21615,10 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +#endif
 +#endif
 +
++#ifdef CONFIG_AUFS_SBILIST
++      struct list_head        si_list;
++#endif
++
 +      /* dirty, necessary for unmounting, sysfs and sysrq */
 +      struct super_block      *si_sb;
 +};
@@ -21241,6 +21660,8 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +#define AuLock_IW             (1 << 2)        /* write-lock inode */
 +#define AuLock_FLUSH          (1 << 3)        /* wait for 'nowait' tasks */
 +#define AuLock_DIR            (1 << 4)        /* target is a dir */
++#define AuLock_NOPLM          (1 << 5)        /* return err in plm mode */
++#define AuLock_NOPLMW         (1 << 6)        /* wait for plm mode ends */
 +#define au_ftest_lock(flags, name)    ((flags) & AuLock_##name)
 +#define au_fset_lock(flags, name)     { (flags) |= AuLock_##name; }
 +#define au_fclr_lock(flags, name)     { (flags) &= ~AuLock_##name; }
@@ -21259,11 +21680,13 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +unsigned int au_sigen_inc(struct super_block *sb);
 +aufs_bindex_t au_new_br_id(struct super_block *sb);
 +
-+void aufs_read_lock(struct dentry *dentry, int flags);
++int si_read_lock(struct super_block *sb, int flags);
++int si_write_lock(struct super_block *sb, int flags);
++int aufs_read_lock(struct dentry *dentry, int flags);
 +void aufs_read_unlock(struct dentry *dentry, int flags);
 +void aufs_write_lock(struct dentry *dentry);
 +void aufs_write_unlock(struct dentry *dentry);
-+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
++int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
 +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
 +
 +int si_pid_test_slow(struct super_block *sb);
@@ -21321,6 +21744,32 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +
 +/* ---------------------------------------------------------------------- */
 +
++#ifdef CONFIG_AUFS_SBILIST
++/* module.c */
++extern struct au_splhead au_sbilist;
++
++static inline void au_sbilist_init(void)
++{
++      au_spl_init(&au_sbilist);
++}
++
++static inline void au_sbilist_add(struct super_block *sb)
++{
++      au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
++}
++
++static inline void au_sbilist_del(struct super_block *sb)
++{
++      au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
++}
++#else
++AuStubVoid(au_sbilist_init, void)
++AuStubVoid(au_sbilist_add, struct super_block*)
++AuStubVoid(au_sbilist_del, struct super_block*)
++#endif
++
++/* ---------------------------------------------------------------------- */
++
 +static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
 +{
 +      /*
@@ -21417,19 +21866,14 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +      return locked;
 +}
 +
-+static inline void si_read_lock(struct super_block *sb, int flags)
-+{
-+      if (au_ftest_lock(flags, FLUSH))
-+              au_nwt_flush(&au_sbi(sb)->si_nowait);
-+      si_noflush_read_lock(sb);
-+}
-+
++#if 0 /* unused */
 +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);
 +}
++#endif
 +
 +static inline void si_read_unlock(struct super_block *sb)
 +{
@@ -21437,12 +21881,6 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +      __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)
 +{
@@ -21508,7 +21946,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
 +#endif /* __AUFS_SUPER_H__ */
 diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
 --- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sysaufs.c    2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/sysaufs.c    2010-10-01 13:09:26.489878162 +0200
 @@ -0,0 +1,107 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -21539,7 +21977,7 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
 +#include "aufs.h"
 +
 +unsigned long sysaufs_si_mask;
-+struct kset *sysaufs_ket;
++struct kset *sysaufs_kset;
 +
 +#define AuSiAttr(_name) { \
 +      .attr   = { .name = __stringify(_name), .mode = 0444 }, \
@@ -21568,10 +22006,10 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
 +{
 +      int err;
 +
-+      sbinfo->si_kobj.kset = sysaufs_ket;
++      sbinfo->si_kobj.kset = sysaufs_kset;
 +      /* cf. sysaufs_name() */
 +      err = kobject_init_and_add
-+              (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
++              (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
 +               SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
 +
 +      dbgaufs_si_null(sbinfo);
@@ -21586,8 +22024,8 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
 +void sysaufs_fin(void)
 +{
 +      dbgaufs_fin();
-+      sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
-+      kset_unregister(sysaufs_ket);
++      sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
++      kset_unregister(sysaufs_kset);
 +}
 +
 +int __init sysaufs_init(void)
@@ -21599,27 +22037,27 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
 +      } while (!sysaufs_si_mask);
 +
 +      err = -EINVAL;
-+      sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
-+      if (unlikely(!sysaufs_ket))
++      sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
++      if (unlikely(!sysaufs_kset))
 +              goto out;
-+      err = PTR_ERR(sysaufs_ket);
-+      if (IS_ERR(sysaufs_ket))
++      err = PTR_ERR(sysaufs_kset);
++      if (IS_ERR(sysaufs_kset))
 +              goto out;
-+      err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
++      err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
 +      if (unlikely(err)) {
-+              kset_unregister(sysaufs_ket);
++              kset_unregister(sysaufs_kset);
 +              goto out;
 +      }
 +
 +      err = dbgaufs_init();
 +      if (unlikely(err))
 +              sysaufs_fin();
-+ out:
++out:
 +      return err;
 +}
 diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
 --- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sysaufs.h    2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/sysaufs.h    2010-10-01 13:09:26.489878162 +0200
 @@ -0,0 +1,105 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -21664,7 +22102,7 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
 +
 +/* sysaufs.c */
 +extern unsigned long sysaufs_si_mask;
-+extern struct kset *sysaufs_ket;
++extern struct kset *sysaufs_kset;
 +extern struct attribute *sysaufs_si_attrs[];
 +int sysaufs_si_init(struct au_sbinfo *sbinfo);
 +int __init sysaufs_init(void);
@@ -21728,7 +22166,7 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
 +#endif /* __SYSAUFS_H__ */
 diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
 --- /usr/share/empty/fs/aufs/sysfs.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sysfs.c      2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/sysfs.c      2010-10-01 13:09:26.490878165 +0200
 @@ -0,0 +1,251 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -21912,7 +22350,7 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
 +      }
 +      BUG();
 +
-+ out_seq:
++out_seq:
 +      if (!err) {
 +              err = seq->count;
 +              /* sysfs limit */
@@ -21920,9 +22358,9 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
 +                      err = -EFBIG;
 +      }
 +      kfree(seq);
-+ out_unlock:
++out_unlock:
 +      si_read_unlock(sb);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -21983,7 +22421,7 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
 +}
 diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
 --- /usr/share/empty/fs/aufs/sysrq.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sysrq.c      2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/sysrq.c      2010-10-01 13:09:26.490878165 +0200
 @@ -0,0 +1,119 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -22023,7 +22461,6 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
 +
 +      plevel = au_plevel;
 +      au_plevel = KERN_WARNING;
-+      au_debug(1);
 +
 +      sbinfo = au_sbi(sb);
 +      /* since we define pr_fmt, call printk directly */
@@ -22037,20 +22474,24 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
 +#if 0
 +      struct inode *i;
 +      printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
++      spin_lock(&inode_lock);
 +      list_for_each_entry(i, &sb->s_inodes, i_sb_list)
 +              if (list_empty(&i->i_dentry))
 +                      au_dpri_inode(i);
++      spin_unlock(&inode_lock);
 +#endif
 +      printk(KERN_WARNING AUFS_NAME ": files\n");
++      file_list_lock();
 +      list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
 +              umode_t mode;
 +              mode = file->f_dentry->d_inode->i_mode;
 +              if (!special_file(mode) || au_special_file(mode))
 +                      au_dpri_file(file);
 +      }
++      file_list_unlock();
++      printk(KERN_WARNING AUFS_NAME ": done\n");
 +
 +      au_plevel = plevel;
-+      au_debug(0);
 +}
 +
 +/* ---------------------------------------------------------------------- */
@@ -22063,15 +22504,12 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
 +static void au_sysrq(int key __maybe_unused,
 +                   struct tty_struct *tty __maybe_unused)
 +{
-+      struct kobject *kobj;
 +      struct au_sbinfo *sbinfo;
 +
-+      /* spin_lock(&sysaufs_ket->list_lock); */
-+      list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
-+              sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++      spin_lock(&au_sbilist.spin);
++      list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
 +              sysrq_sb(sbinfo->si_sb);
-+      }
-+      /* spin_unlock(&sysaufs_ket->list_lock); */
++      spin_unlock(&au_sbilist.spin);
 +}
 +
 +static struct sysrq_key_op au_sysrq_op = {
@@ -22106,7 +22544,7 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
 +}
 diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 --- /usr/share/empty/fs/aufs/vdir.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/vdir.c       2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/vdir.c       2010-10-01 13:09:26.490878165 +0200
 @@ -0,0 +1,884 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -22381,7 +22819,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +      hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
 +      /* smp_mb(); */
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -22410,7 +22848,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +              err = set_deblk_end(&p, &deblk_end);
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -22459,7 +22897,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +              err = append_deblk(vdir);
 +      /* smp_mb(); */
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -22509,9 +22947,9 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +
 +      kfree(vdir->vd_deblk);
 +
-+ out_free:
++out_free:
 +      au_cache_free_vdir(vdir);
-+ out:
++out:
 +      vdir = ERR_PTR(err);
 +      return vdir;
 +}
@@ -22608,7 +23046,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +              }
 +      }
 +
-+ out:
++out:
 +      if (!arg->err)
 +              arg->vdir->vd_jiffy = jiffies;
 +      /* smp_mb(); */
@@ -22653,7 +23091,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +
 +      __putname(o);
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +#else
@@ -22725,9 +23163,9 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +
 +      au_nhash_wh_free(&arg->whlist);
 +
-+ out_delist:
++out_delist:
 +      au_nhash_de_free(&arg->delist);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -22782,7 +23220,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +      } else if (allocated)
 +              au_vdir_free(allocated);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -22834,7 +23272,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +      /* smp_mb(); */
 +      return 0; /* success */
 +
-+ out:
++out:
 +      rerr = reinit_vdir(tgt);
 +      BUG_ON(rerr);
 +      return err;
@@ -22874,7 +23312,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +      } else if (allocated)
 +              au_vdir_free(allocated);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -22939,7 +23377,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +              }
 +      }
 +
-+ out:
++out:
 +      /* smp_mb(); */
 +      AuTraceErr(!valid);
 +      return valid;
@@ -22994,7 +23432,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +}
 diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 --- /usr/share/empty/fs/aufs/vfsub.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/vfsub.c      2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/vfsub.c      2010-10-01 13:09:26.490878165 +0200
 @@ -0,0 +1,786 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -23103,7 +23541,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              goto out;
 +      vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
 +
-+ out:
++out:
 +      return file;
 +}
 +
@@ -23133,7 +23571,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +      if (path.dentry->d_inode)
 +              vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
 +
-+ out:
++out:
 +      AuTraceErrPtr(path.dentry);
 +      return path.dentry;
 +}
@@ -23152,7 +23590,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +      if (path.dentry->d_inode)
 +              vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
 +
-+ out:
++out:
 +      AuTraceErrPtr(path.dentry);
 +      return path.dentry;
 +}
@@ -23226,7 +23664,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              /*ignore*/
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23257,7 +23695,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              /*ignore*/
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23288,7 +23726,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              /*ignore*/
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23336,7 +23774,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              /*ignore*/
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23375,7 +23813,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              /*ignore*/
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23406,7 +23844,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              /*ignore*/
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23434,7 +23872,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +              vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23575,13 +24013,13 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +      if (!err)
 +              err = do_truncate(h_path->dentry, length, attr, h_file);
 +
-+ out_inode:
++out_inode:
 +      if (!h_file)
 +              put_write_access(h_inode);
-+ out_mnt:
++out_mnt:
 +      if (!h_file)
 +              mnt_drop_write(h_path->mnt);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -23784,7 +24222,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
 +}
 diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
 --- /usr/share/empty/fs/aufs/vfsub.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/vfsub.h      2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/vfsub.h      2010-10-01 13:09:26.490878165 +0200
 @@ -0,0 +1,174 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -23962,7 +24400,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
 +#endif /* __AUFS_VFSUB_H__ */
 diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 --- /usr/share/empty/fs/aufs/wbr_policy.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wbr_policy.c 2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/wbr_policy.c 2010-10-01 13:09:26.491878167 +0200
 @@ -0,0 +1,696 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -24042,7 +24480,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +      dput(opq_dentry);
 +      au_fset_cpdown(a->flags, DIROPQ);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -24067,7 +24505,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +      }
 +      dput(h_path.dentry);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -24136,7 +24574,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +      goto out; /* success */
 +
 +      /* revert */
-+ out_opq:
++out_opq:
 +      if (au_ftest_cpdown(args->flags, DIROPQ)) {
 +              mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
 +              rerr = au_diropq_remove(dentry, bdst);
@@ -24148,7 +24586,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +                      goto out;
 +              }
 +      }
-+ out_dir:
++out_dir:
 +      if (au_ftest_cpdown(args->flags, MADE_DIR)) {
 +              rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
 +              if (unlikely(rerr)) {
@@ -24157,11 +24595,11 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +                      err = -EIO;
 +              }
 +      }
-+ out_put:
++out_put:
 +      au_set_h_dptr(dentry, bdst, NULL);
 +      if (au_dbend(dentry) == bdst)
 +              au_update_dbend(dentry);
-+ out:
++out:
 +      dput(parent);
 +      return err;
 +}
@@ -24266,7 +24704,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +                      err = au_wbr_nonopq(dentry, err);
 +      }
 +
-+ out:
++out:
 +      AuDbg("b%d\n", err);
 +      return err;
 +}
@@ -24357,7 +24795,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +      if (err >= 0)
 +              err = au_wbr_nonopq(dentry, err);
 +
-+ out:
++out:
 +      AuDbg("%d\n", err);
 +      return err;
 +}
@@ -24441,7 +24879,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +      if (err >= 0)
 +              err = au_wbr_nonopq(dentry, err);
 +
-+ out:
++out:
 +      AuDbg("b%d\n", err);
 +      return err;
 +}
@@ -24542,9 +24980,9 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +      if (err >= 0)
 +              err = au_wbr_nonopq(dentry, err);
 +
-+ out_parent:
++out_parent:
 +      dput(parent);
-+ out:
++out:
 +      AuDbg("b%d\n", err);
 +      return err;
 +}
@@ -24662,8 +25100,8 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +};
 diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 --- /usr/share/empty/fs/aufs/whout.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/whout.c      2010-08-21 21:00:02.986708041 +0200
-@@ -0,0 +1,1052 @@
++++ linux/fs/aufs/whout.c      2010-10-01 13:09:26.491878167 +0200
+@@ -0,0 +1,1059 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -24759,9 +25197,9 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
 +              AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
 +
-+ out_wh:
++out_wh:
 +      dput(wh_dentry);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -24827,10 +25265,10 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      AuDbg("%.*s\n", AuLNPair(&qs));
 +      BUG();
 +
-+ out_name:
++out_name:
 +      if (name != defname)
 +              kfree(name);
-+ out:
++out:
 +      AuTraceErrPtr(dentry);
 +      return dentry;
 +}
@@ -24861,7 +25299,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      AuTraceErr(err);
 +      dput(h_path.dentry);
 +
-+ out:
++out:
 +      AuTraceErr(err);
 +      return err;
 +}
@@ -25032,7 +25470,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +              goto out;
 +      wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -25095,7 +25533,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +              goto out;
 +      wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -25197,10 +25635,10 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      }
 +      goto out; /* success */
 +
-+ out_err:
++out_err:
 +      pr_err("an error(%d) on the writable branch %.*s(%s)\n",
 +             err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
-+ out:
++out:
 +      for (i = 0; i < AuBrWh_Last; i++)
 +              dput(base[i].dentry);
 +      return err;
@@ -25269,7 +25707,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      au_hn_imtx_unlock(hdir);
 +      di_read_unlock(a->sb->s_root, AuLock_IR);
 +
-+ out:
++out:
 +      if (wbr)
 +              atomic_dec(&wbr->wbr_wh_running);
 +      atomic_dec(&a->br->br_count);
@@ -25308,7 +25746,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +              do_dec = 0;
 +      }
 +
-+ out:
++out:
 +      if (do_dec)
 +              atomic_dec(&br->br_wbr->wbr_wh_running);
 +}
@@ -25350,7 +25788,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      /* return this error in this context */
 +      err = vfsub_create(h_dir, &h_path, WH_MASK);
 +
-+ out:
++out:
 +      wbr_wh_read_unlock(wbr);
 +      return err;
 +}
@@ -25393,7 +25831,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      dput(opq_dentry);
 +      opq_dentry = ERR_PTR(err);
 +
-+ out:
++out:
 +      return opq_dentry;
 +}
 +
@@ -25532,7 +25970,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +      }
 +      __putname(wh_name.name);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -25578,7 +26016,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +              whtmp = ERR_PTR(err);
 +      }
 +
-+ out:
++out:
 +      return whtmp;
 +}
 +
@@ -25654,43 +26092,47 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +static void call_rmdir_whtmp(void *args)
 +{
 +      int err;
++      aufs_bindex_t bindex;
 +      struct au_whtmp_rmdir *a = args;
 +      struct super_block *sb;
 +      struct dentry *h_parent;
 +      struct inode *h_dir;
-+      struct au_branch *br;
 +      struct au_hinode *hdir;
 +
 +      /* rmdir by nfsd may cause deadlock with this i_mutex */
 +      /* mutex_lock(&a->dir->i_mutex); */
++      err = -EROFS;
 +      sb = a->dir->i_sb;
-+      si_noflush_read_lock(sb);
-+      err = au_test_ro(sb, a->bindex, NULL);
-+      if (unlikely(err))
++      si_read_lock(sb, !AuLock_FLUSH);
++      if (!au_br_writable(a->br->br_perm))
++              goto out;
++      bindex = au_br_index(sb, a->br->br_id);
++      if (unlikely(bindex < 0))
 +              goto out;
 +
 +      err = -EIO;
-+      br = au_sbr(sb, a->bindex);
 +      ii_write_lock_parent(a->dir);
 +      h_parent = dget_parent(a->wh_dentry);
 +      h_dir = h_parent->d_inode;
-+      hdir = au_hi(a->dir, a->bindex);
++      hdir = au_hi(a->dir, bindex);
 +      au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
-+      err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
++      err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
++                        a->br);
 +      if (!err) {
-+              err = mnt_want_write(br->br_mnt);
++              err = mnt_want_write(a->br->br_mnt);
 +              if (!err) {
-+                      err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
++                      err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
 +                                           &a->whlist);
-+                      mnt_drop_write(br->br_mnt);
++                      mnt_drop_write(a->br->br_mnt);
 +              }
 +      }
 +      au_hn_imtx_unlock(hdir);
 +      dput(h_parent);
 +      ii_write_unlock(a->dir);
 +
-+ out:
++out:
 +      /* mutex_unlock(&a->dir->i_mutex); */
++      atomic_dec(&a->br->br_count);
 +      au_nwt_done(&au_sbi(sb)->si_nowait);
 +      si_read_unlock(sb);
 +      au_whtmp_rmdir_free(a);
@@ -25702,14 +26144,17 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +                       struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
 +{
 +      int wkq_err;
++      struct super_block *sb;
 +
 +      IMustLock(dir);
 +
 +      /* all post-process will be done in do_rmdir_whtmp(). */
++      sb = dir->i_sb;
 +      args->dir = au_igrab(dir);
-+      args->bindex = bindex;
++      args->br = au_sbr(sb, bindex);
++      atomic_inc(&args->br->br_count);
 +      args->wh_dentry = dget(wh_dentry);
-+      wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
++      wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb);
 +      if (unlikely(wkq_err)) {
 +              pr_warning("rmdir error %.*s (%d), ignored\n",
 +                         AuDLNPair(wh_dentry), wkq_err);
@@ -25718,7 +26163,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +}
 diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
 --- /usr/share/empty/fs/aufs/whout.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/whout.h      2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/whout.h      2010-10-01 13:09:26.491878167 +0200
 @@ -0,0 +1,87 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -25780,7 +26225,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
 +/* real rmdir for the whiteout-ed dir */
 +struct au_whtmp_rmdir {
 +      struct inode *dir;
-+      aufs_bindex_t bindex;
++      struct au_branch *br;
 +      struct dentry *wh_dentry;
 +      struct au_nhash whlist;
 +};
@@ -25809,7 +26254,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
 +#endif /* __AUFS_WHOUT_H__ */
 diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
 --- /usr/share/empty/fs/aufs/wkq.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wkq.c        2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/wkq.c        2010-10-01 13:09:26.491878167 +0200
 @@ -0,0 +1,223 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -25989,7 +26434,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
 +              au_wkq_run(wkinfo, !AuWkq_WAIT);
 +      } else {
 +              err = -ENOMEM;
-+              atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
++              au_nwt_done(&au_sbi(sb)->si_nowait);
 +      }
 +
 +      return err;
@@ -26036,7 +26481,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
 +}
 diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
 --- /usr/share/empty/fs/aufs/wkq.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wkq.h        2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/wkq.h        2010-10-01 13:09:26.491878167 +0200
 @@ -0,0 +1,88 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -26114,7 +26559,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
 +
 +static inline void au_nwt_done(struct au_nowait_tasks *nwt)
 +{
-+      if (!atomic_dec_return(&nwt->nw_len))
++      if (atomic_dec_and_test(&nwt->nw_len))
 +              wake_up_all(&nwt->nw_wq);
 +}
 +
@@ -26128,7 +26573,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
 +#endif /* __AUFS_WKQ_H__ */
 diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 --- /usr/share/empty/fs/aufs/xino.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/xino.c       2010-08-21 21:00:02.986708041 +0200
++++ linux/fs/aufs/xino.c       2010-10-01 13:09:26.491878167 +0200
 @@ -0,0 +1,1263 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -26323,12 +26768,12 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +      }
 +      goto out_dput; /* success */
 +
-+ out_fput:
++out_fput:
 +      fput(file);
 +      file = ERR_PTR(err);
-+ out_dput:
++out_dput:
 +      dput(path.dentry);
-+ out:
++out:
 +      return file;
 +}
 +
@@ -26414,7 +26859,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +              get_file(new_xino);
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -26475,7 +26920,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +              goto out_args;
 +      }
 +
-+      atomic_inc_return(&br->br_count);
++      atomic_inc(&br->br_count);
 +      args->sb = sb;
 +      args->br = br;
 +      wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
@@ -26483,12 +26928,12 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +              return; /* success */
 +
 +      pr_err("wkq %d\n", wkq_err);
-+      atomic_dec_return(&br->br_count);
++      atomic_dec(&br->br_count);
 +
-+ out_args:
++out_args:
 +      kfree(args);
-+ out:
-+      atomic_dec_return(&br->br_xino_running);
++out:
++      atomic_dec(&br->br_xino_running);
 +}
 +
 +/* ---------------------------------------------------------------------- */
@@ -26609,7 +27054,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +              return 0; /* success */
 +      }
 +
-+ out:
++out:
 +      AuIOErr1("write failed (%zd)\n", sz);
 +      err = sz;
 +      if (sz >= 0)
@@ -26742,7 +27187,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +      }
 +      BUG();
 +
-+ out:
++out:
 +      set_bit(free_bit, p);
 +      sbinfo->si_xib_next_bit++;
 +      pindex = sbinfo->si_xib_last_pindex;
@@ -26750,7 +27195,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +      ino = xib_calc_ino(pindex, free_bit);
 +      AuDbg("i%lu\n", (unsigned long)ino);
 +      return ino;
-+ out_err:
++out_err:
 +      mutex_unlock(&sbinfo->si_xib_mtx);
 +      AuDbg("i0\n");
 +      return 0;
@@ -26853,7 +27298,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +      }
 +      return file; /* success */
 +
-+ out:
++out:
 +      fput(file);
 +      file = ERR_PTR(err);
 +      return file;
@@ -26933,7 +27378,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +              br->br_xino.xi_file = NULL;
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -26981,7 +27426,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +              }
 +      }
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -27006,7 +27451,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +                      AuDbg("b%d\n", bindex);
 +      free_page((unsigned long)page);
 +
-+ out:
++out:
 +      return err;
 +}
 +
@@ -27148,17 +27593,17 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +      err = 0;
 +      goto out; /* success */
 +
-+ out_free:
++out_free:
 +      free_page((unsigned long)sbinfo->si_xib_buf);
 +      sbinfo->si_xib_buf = NULL;
 +      if (err >= 0)
 +              err = -EIO;
-+ out_unset:
++out_unset:
 +      fput(sbinfo->si_xib);
 +      sbinfo->si_xib = NULL;
 +      sbinfo->si_xread = NULL;
 +      sbinfo->si_xwrite = NULL;
-+ out:
++out:
 +      return err;
 +}
 +
@@ -27236,14 +27681,14 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +              br->br_xino.xi_file = p->new;
 +      }
 +
-+ out_pair:
++out_pair:
 +      for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
 +              if (p->new)
 +                      fput(p->new);
 +              else
 +                      break;
 +      kfree(fpair);
-+ out:
++out:
 +      return err;
 +}
 +
@@ -27306,7 +27751,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +      /* reset all */
 +      AuIOErr("failed creating xino(%d).\n", err);
 +
-+ out:
++out:
 +      dput(parent);
 +      return err;
 +}
@@ -27369,7 +27814,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +                      au_xino_brid_set(sb, -1);
 +      }
 +
-+ out:
++out:
 +      return file;
 +}
 +
@@ -27390,13 +27835,13 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +                       sizeof(Deleted) - 1));
 +#undef Deleted
 +
-+ out:
++out:
 +      return err;
 +}
 diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
 --- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/include/linux/aufs_type.h    2010-08-21 21:00:02.989917215 +0200
-@@ -0,0 +1,198 @@
++++ linux/include/linux/aufs_type.h    2010-10-01 13:09:26.492878168 +0200
+@@ -0,0 +1,195 @@
 +/*
 + * Copyright (C) 2005-2010 Junjiro R. Okajima
 + *
@@ -27419,14 +27864,11 @@ diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_ty
 +#define __AUFS_TYPE_H__
 +
 +#include <linux/ioctl.h>
-+/* for those who didn't "make headers_install" */
-+#ifdef __KERNEL__
 +#include <linux/kernel.h>
-+#endif
 +#include <linux/limits.h>
 +#include <linux/types.h>
 +
-+#define AUFS_VERSION  "2-standalone.tree-35-20100816"
++#define AUFS_VERSION  "2.1-standalone.tree-35-20100920"
 +
 +/* todo? move this to linux-2.6.19/include/magic.h */
 +#define AUFS_SUPER_MAGIC      ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -27482,6 +27924,11 @@ diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_ty
 +#define AUFS_MFS_SECOND_DEF   30 /* seconds */
 +#define AUFS_PLINK_WARN               100 /* number of plinks */
 +
++/* pseudo-link maintenace under /proc */
++#define AUFS_PLINK_MAINT_NAME "plink_maint"
++#define AUFS_PLINK_MAINT_DIR  "fs/" AUFS_NAME
++#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
++
 +#define AUFS_DIROPQ_NAME      AUFS_WH_PFX ".opq" /* whiteouted doubly */
 +#define AUFS_WH_DIROPQ                AUFS_WH_PFX AUFS_DIROPQ_NAME
 +
@@ -27508,9 +27955,6 @@ diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_ty
 +
 +/* ioctl */
 +enum {
-+      AuCtl_PLINK_MAINT,
-+      AuCtl_PLINK_CLEAN,
-+
 +      /* readdir in userspace */
 +      AuCtl_RDU,
 +      AuCtl_RDU_INO,
@@ -27588,8 +28032,6 @@ diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_ty
 +} __aligned(8);
 +
 +#define AuCtlType             'A'
-+#define AUFS_CTL_PLINK_MAINT  _IO(AuCtlType, AuCtl_PLINK_MAINT)
-+#define AUFS_CTL_PLINK_CLEAN  _IO(AuCtlType, AuCtl_PLINK_CLEAN)
 +#define AUFS_CTL_RDU          _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
 +#define AUFS_CTL_RDU_INO      _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
 +#define AUFS_CTL_WBR_FD               _IO(AuCtlType, AuCtl_WBR_FD)
index 7e6cbdcb332b104fcee1ab06cbecfd62ab17e49e..5c9ad1c246e88f45b197ec1b3612ce5d5213dc7f 100644 (file)
@@ -282,7 +282,7 @@ Patch140:   kernel-unionfs.patch
 # Patch creation:
 # git clone http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-standalone.git
 # cd aufs2-standalone.git
-# git checkout -b aufs2-35 origin/aufs2-35
+# git checkout -b aufs2.1-35 origin/aufs2.1-35
 # cat aufs2-kbuild.patch aufs2-base.patch aufs2-standalone.patch > ~/rpm/packages/kernel/kernel-aufs2.patch
 # mkdir linux
 # cp -a Documentation fs include linux
@@ -291,6 +291,7 @@ Patch140:   kernel-unionfs.patch
 Patch145:      kernel-aufs2.patch
 Patch146:      kernel-aufs2-unionfs.patch
 Patch147:      kernel-aufs2-no-const-grsec.patch
+Patch148:      kernel-aufs2-reiser4.patch
 
 Patch150:      kernel-ppc-crtsavres.patch
 
@@ -797,6 +798,9 @@ sed -i 's/-Werror//' arch/alpha/kernel/Makefile
 %patch131 -p1
 
 # aufs2
+%if %{with reiser4}
+%patch148 -p1
+%endif
 %patch145 -p1
 %patch146 -p1
 
This page took 0.426762 seconds and 4 git commands to generate.