]> git.ipfire.org Git - ipfire-3.x.git/commitdiff
kernel: Readded aufs, again.
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 5 Apr 2010 15:21:33 +0000 (17:21 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 5 Apr 2010 15:21:33 +0000 (17:21 +0200)
pkgs/core/kernel/config
pkgs/core/kernel/patches/aufs2-2.6.33.1-1.patch [moved from pkgs/core/kernel/patches/aufs2-2.6.31.1-1.patch.off with 87% similarity]

index 27a349e4e8fc071eea5192fe70124e040cc4152b..7c4f9e5d5d768c9b50026bca7fba5d2009552d21 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.33.1
-# Sun Mar 21 20:09:46 2010
+# Mon Apr  5 15:20:41 2010
 #
 # CONFIG_64BIT is not set
 CONFIG_X86_32=y
@@ -3268,8 +3268,6 @@ CONFIG_JBD=m
 CONFIG_JBD2=m
 # CONFIG_JBD2_DEBUG is not set
 CONFIG_FS_MBCACHE=m
-CONFIG_REISER4_FS=m
-# CONFIG_REISER4_DEBUG is not set
 CONFIG_REISERFS_FS=m
 # CONFIG_REISERFS_CHECK is not set
 CONFIG_REISERFS_PROC_INFO=y
@@ -3366,6 +3364,20 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_EXOFS_FS is not set
+CONFIG_AUFS_FS=m
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+# CONFIG_AUFS_HNOTIFY is not set
+# CONFIG_AUFS_EXPORT is not set
+# CONFIG_AUFS_RDU is not set
+CONFIG_AUFS_SP_IATTR=y
+# CONFIG_AUFS_SHWH is not set
+# CONFIG_AUFS_BR_RAMFS is not set
+# CONFIG_AUFS_BR_FUSE is not set
+CONFIG_AUFS_BDEV_LOOP=y
+# CONFIG_AUFS_DEBUG is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
similarity index 87%
rename from pkgs/core/kernel/patches/aufs2-2.6.31.1-1.patch.off
rename to pkgs/core/kernel/patches/aufs2-2.6.33.1-1.patch
index 1f6f6126ec78adb3f877571f2296439457cc28ee..ef625f495fa4143a5abe75389134ccca6465c0b5 100644 (file)
@@ -1,6 +1,6 @@
-diff -Nur linux-2.6.31-vanilla/Documentation/ABI/testing/debugfs-aufs linux-2.6.31/Documentation/ABI/testing/debugfs-aufs
---- linux-2.6.31-vanilla/Documentation/ABI/testing/debugfs-aufs        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/Documentation/ABI/testing/debugfs-aufs        2009-09-16 13:55:29.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/Documentation/ABI/testing/debugfs-aufs linux-2.6.33.1/Documentation/ABI/testing/debugfs-aufs
+--- linux-2.6.33.1-vanilla/Documentation/ABI/testing/debugfs-aufs      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/Documentation/ABI/testing/debugfs-aufs      2010-04-05 16:48:57.000000000 +0200
 @@ -0,0 +1,40 @@
 +What:         /debug/aufs/si_<id>/
 +Date:         March 2009
@@ -42,9 +42,9 @@ diff -Nur linux-2.6.31-vanilla/Documentation/ABI/testing/debugfs-aufs linux-2.6.
 +              When the aufs mount option 'noxino' is specified, it
 +              will be empty. About XINO files, see
 +              Documentation/filesystems/aufs/aufs.5 in detail.
-diff -Nur linux-2.6.31-vanilla/Documentation/ABI/testing/sysfs-aufs linux-2.6.31/Documentation/ABI/testing/sysfs-aufs
---- linux-2.6.31-vanilla/Documentation/ABI/testing/sysfs-aufs  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/Documentation/ABI/testing/sysfs-aufs  2009-09-16 13:55:29.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/Documentation/ABI/testing/sysfs-aufs linux-2.6.33.1/Documentation/ABI/testing/sysfs-aufs
+--- linux-2.6.33.1-vanilla/Documentation/ABI/testing/sysfs-aufs        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/Documentation/ABI/testing/sysfs-aufs        2010-04-05 16:48:57.000000000 +0200
 @@ -0,0 +1,25 @@
 +What:         /sys/fs/aufs/si_<id>/
 +Date:         March 2009
@@ -71,12 +71,12 @@ diff -Nur linux-2.6.31-vanilla/Documentation/ABI/testing/sysfs-aufs linux-2.6.31
 +              When the aufs mount option 'noxino' is specified, it
 +              will be empty. About XINO files, see
 +              Documentation/filesystems/aufs/aufs.5 in detail.
-diff -Nur linux-2.6.31-vanilla/fs/aufs/aufs.h linux-2.6.31/fs/aufs/aufs.h
---- linux-2.6.31-vanilla/fs/aufs/aufs.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/aufs.h        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,51 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/aufs.h linux-2.6.33.1/fs/aufs/aufs.h
+--- linux-2.6.33.1-vanilla/fs/aufs/aufs.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/aufs.h      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,59 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -102,6 +102,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/aufs.h linux-2.6.31/fs/aufs/aufs.h
 +
 +#ifdef __KERNEL__
 +
++#define AuStub(type, name, body, ...) \
++      static inline type name(__VA_ARGS__) { body; }
++
++#define AuStubVoid(name, ...) \
++      AuStub(void, name, , __VA_ARGS__)
++#define AuStubInt0(name, ...) \
++      AuStub(int, name, return 0, __VA_ARGS__)
++
 +#include "debug.h"
 +
 +#include "branch.h"
@@ -126,12 +134,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/aufs.h linux-2.6.31/fs/aufs/aufs.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
---- linux-2.6.31-vanilla/fs/aufs/branch.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/branch.c      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,969 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/branch.c linux-2.6.33.1/fs/aufs/branch.c
+--- linux-2.6.33.1-vanilla/fs/aufs/branch.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/branch.c    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,996 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -153,6 +161,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 + */
 +
 +#include <linux/file.h>
++#include <linux/statfs.h>
 +#include "aufs.h"
 +
 +/*
@@ -178,9 +187,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      }
 +
 +      /* some filesystems acquire extra lock */
-+      lockdep_off();
++      /* lockdep_off(); */
 +      mntput(br->br_mnt);
-+      lockdep_on();
++      /* lockdep_on(); */
 +
 +      kfree(wbr);
 +      kfree(br);
@@ -242,7 +251,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +{
 +      struct au_branch *add_branch;
 +      struct dentry *root;
++      int err;
 +
++      err = -ENOMEM;
 +      root = sb->s_root;
 +      add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
 +      if (unlikely(!add_branch))
@@ -257,18 +268,20 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +                      goto out_br;
 +      }
 +
-+      if (unlikely(au_sbr_realloc(au_sbi(sb), new_nbranch)
-+                   || au_di_realloc(au_di(root), new_nbranch)
-+                   || au_ii_realloc(au_ii(root->d_inode), new_nbranch)))
-+              goto out_wbr;
-+      return add_branch; /* success */
++      err = au_sbr_realloc(au_sbi(sb), new_nbranch);
++      if (!err)
++              err = au_di_realloc(au_di(root), new_nbranch);
++      if (!err)
++              err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
++      if (!err)
++              return add_branch; /* success */
 +
-+ out_wbr:
 +      kfree(add_branch->br_wbr);
++
 + out_br:
 +      kfree(add_branch);
 + out:
-+      return ERR_PTR(-ENOMEM);
++      return ERR_PTR(err);
 +}
 +
 +/*
@@ -278,13 +291,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +{
 +      int err;
 +
-+      err = 0;
-+      if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
-+              AuErr("write permission for readonly mount or inode, %s\n",
-+                    path);
-+              err = -EINVAL;
-+      }
++      err = (au_br_writable(brperm) && IS_RDONLY(inode));
++      if (!err)
++              goto out;
++
++      err = -EINVAL;
++      pr_err("write permission for readonly mount or inode, %s\n", path);
 +
++ out:
 +      return err;
 +}
 +
@@ -308,7 +322,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +              err = 1;
 +              if (!remount) {
 +                      err = -EINVAL;
-+                      AuErr("%s duplicated\n", add->pathname);
++                      pr_err("%s duplicated\n", add->pathname);
 +              }
 +              goto out;
 +      }
@@ -316,32 +330,32 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      err = -ENOSPC; /* -E2BIG; */
 +      if (unlikely(AUFS_BRANCH_MAX <= add->bindex
 +                   || AUFS_BRANCH_MAX - 1 <= bend)) {
-+              AuErr("number of branches exceeded %s\n", add->pathname);
++              pr_err("number of branches exceeded %s\n", add->pathname);
 +              goto out;
 +      }
 +
 +      err = -EDOM;
 +      if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
-+              AuErr("bad index %d\n", add->bindex);
++              pr_err("bad index %d\n", add->bindex);
 +              goto out;
 +      }
 +
 +      inode = add->path.dentry->d_inode;
 +      err = -ENOENT;
 +      if (unlikely(!inode->i_nlink)) {
-+              AuErr("no existence %s\n", add->pathname);
++              pr_err("no existence %s\n", add->pathname);
 +              goto out;
 +      }
 +
 +      err = -EINVAL;
 +      if (unlikely(inode->i_sb == sb)) {
-+              AuErr("%s must be outside\n", add->pathname);
++              pr_err("%s must be outside\n", add->pathname);
 +              goto out;
 +      }
 +
 +      if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
-+              AuErr("unsupported filesystem, %s (%s)\n",
-+                    add->pathname, au_sbtype(inode->i_sb));
++              pr_err("unsupported filesystem, %s (%s)\n",
++                     add->pathname, au_sbtype(inode->i_sb));
 +              goto out;
 +      }
 +
@@ -356,7 +370,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      for (bindex = 0; bindex <= bend; bindex++)
 +              if (unlikely(test_overlap(sb, add->path.dentry,
 +                                        au_h_dptr(root, bindex)))) {
-+                      AuErr("%s is overlapped\n", add->pathname);
++                      pr_err("%s is overlapped\n", add->pathname);
 +                      goto out;
 +              }
 +
@@ -366,12 +380,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +              if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
 +                  || h_inode->i_uid != inode->i_uid
 +                  || h_inode->i_gid != inode->i_gid)
-+                      AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
-+                             add->pathname,
-+                             inode->i_uid, inode->i_gid,
-+                             (inode->i_mode & S_IALLUGO),
-+                             h_inode->i_uid, h_inode->i_gid,
-+                             (h_inode->i_mode & S_IALLUGO));
++                      pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
++                                 add->pathname,
++                                 inode->i_uid, inode->i_gid,
++                                 (inode->i_mode & S_IALLUGO),
++                                 h_inode->i_uid, h_inode->i_gid,
++                                 (h_inode->i_mode & S_IALLUGO));
 +      }
 +
 + out:
@@ -398,7 +412,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      bindex = au_br_index(sb, br->br_id);
 +      if (0 <= bindex) {
 +              hdir = au_hi(sb->s_root->d_inode, bindex);
-+              au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++              au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
 +      } else {
 +              h_mtx = &h_root->d_inode->i_mutex;
 +              mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
@@ -411,7 +425,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +              wbr_wh_write_unlock(wbr);
 +      }
 +      if (hdir)
-+              au_hin_imtx_unlock(hdir);
++              au_hn_imtx_unlock(hdir);
 +      else
 +              mutex_unlock(h_mtx);
 +      br->br_perm = old_perm;
@@ -428,7 +442,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +                     int perm, struct path *path)
 +{
 +      int err;
++      struct kstatfs kst;
 +      struct au_wbr *wbr;
++      struct dentry *h_dentry;
 +
 +      wbr = br->br_wbr;
 +      au_rw_init(&wbr->wbr_wh_rwsem);
@@ -436,8 +452,23 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      atomic_set(&wbr->wbr_wh_running, 0);
 +      wbr->wbr_bytes = 0;
 +
-+      err = au_br_init_wh(sb, br, perm, path->dentry);
++      /*
++       * a limit for rmdir/rename a dir
++       * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
++       */
++      h_dentry = path->dentry;
++      err = vfs_statfs(h_dentry, &kst);
++      if (unlikely(err))
++              goto out;
++      err = -EINVAL;
++      if (kst.f_namelen >= NAME_MAX)
++              err = au_br_init_wh(sb, br, perm, h_dentry);
++      else
++              pr_err("%.*s(%s), unsupported namelen %ld\n",
++                     AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
++                     kst.f_namelen);
 +
++ out:
 +      return err;
 +}
 +
@@ -520,7 +551,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      hip = iinfo->ii_hinode + bindex;
 +      memmove(hip + 1, hip, sizeof(*hip) * amount);
 +      hip->hi_inode = NULL;
-+      au_hin_init(hip, NULL);
++      au_hn_init(hip);
 +      iinfo->ii_bend++;
 +      if (unlikely(bend < 0))
 +              iinfo->ii_bstart = 0;
@@ -535,7 +566,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +
 +      root = sb->s_root;
 +      root_inode = root->d_inode;
-+      au_plink_block_maintain(sb);
++      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);
@@ -594,7 +625,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +              au_add_nlink(root_inode, h_dentry->d_inode);
 +
 +      /*
-+       * this test/set prevents aufs from handling unnecesary inotify events
++       * this test/set prevents aufs from handling unnecesary notify events
 +       * of xino files, in a case of re-adding a writable branch which was
 +       * once detached from aufs.
 +       */
@@ -616,9 +647,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 + */
 +
 +/* to show the line number, do not make it inlined function */
-+#define AuVerbose(do_info, fmt, args...) do { \
++#define AuVerbose(do_info, fmt, ...) do { \
 +      if (do_info) \
-+              AuInfo(fmt, ##args); \
++              pr_info(fmt, ##__VA_ARGS__); \
 +} while (0)
 +
 +/*
@@ -761,6 +792,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
 +      if (p)
 +              sbinfo->si_branch = p;
++      /* harmless error */
 +}
 +
 +static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
@@ -779,6 +811,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      p = krealloc(dinfo->di_hdentry, sizeof(*p) * bend, GFP_NOFS);
 +      if (p)
 +              dinfo->di_hdentry = p;
++      /* harmless error */
 +}
 +
 +static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
@@ -792,12 +825,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      if (bindex < bend)
 +              memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
 +      iinfo->ii_hinode[0 + bend].hi_inode = NULL;
-+      au_hin_init(iinfo->ii_hinode + bend, NULL);
++      au_hn_init(iinfo->ii_hinode + bend);
 +      iinfo->ii_bend--;
 +
 +      p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
 +      if (p)
 +              iinfo->ii_hinode = p;
++      /* harmless error */
 +}
 +
 +static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
@@ -812,7 +846,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +
 +      root = sb->s_root;
 +      inode = root->d_inode;
-+      au_plink_block_maintain(sb);
++      au_plink_maint_block(sb);
 +      sbinfo = au_sbi(sb);
 +      bend = sbinfo->si_bend;
 +
@@ -840,7 +874,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +              if (remount)
 +                      goto out; /* success */
 +              err = -ENOENT;
-+              AuErr("%s no such branch\n", del->pathname);
++              pr_err("%s no such branch\n", del->pathname);
 +              goto out;
 +      }
 +      AuDbg("bindex b%d\n", bindex);
@@ -904,8 +938,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      /* revert */
 +      rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
 +      if (rerr)
-+              AuWarn("failed re-creating base whiteout, %s. (%d)\n",
-+                     del->pathname, rerr);
++              pr_warning("failed re-creating base whiteout, %s. (%d)\n",
++                         del->pathname, rerr);
 + out:
 +      return err;
 +}
@@ -919,7 +953,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +static void au_warn_ima(void)
 +{
 +#ifdef CONFIG_IMA
-+      AuWarn("RW -> RO makes IMA to produce wrong message");
++      /* since it doesn't support mark_files_ro() */
++      pr_warning("RW -> RO makes IMA to produce wrong message");
 +#endif
 +}
 +
@@ -1025,13 +1060,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 +      struct au_branch *br;
 +
 +      root = sb->s_root;
-+      au_plink_block_maintain(sb);
++      au_plink_maint_block(sb);
 +      bindex = au_find_dbindex(root, mod->h_root);
 +      if (bindex < 0) {
 +              if (remount)
 +                      return 0; /* success */
 +              err = -ENOENT;
-+              AuErr("%s no such branch\n", mod->path);
++              pr_err("%s no such branch\n", mod->path);
 +              goto out;
 +      }
 +      AuDbg("bindex b%d\n", bindex);
@@ -1099,12 +1134,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.c linux-2.6.31/fs/aufs/branch.c
 + out:
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.h linux-2.6.31/fs/aufs/branch.h
---- linux-2.6.31-vanilla/fs/aufs/branch.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/branch.h      2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/branch.h linux-2.6.33.1/fs/aufs/branch.h
+--- linux-2.6.33.1-vanilla/fs/aufs/branch.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/branch.h    2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,219 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -1155,7 +1190,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.h linux-2.6.31/fs/aufs/branch.h
 +struct au_wbr {
 +      struct au_rwsem         wbr_wh_rwsem;
 +      struct dentry           *wbr_wh[AuBrWh_Last];
-+      atomic_t                wbr_wh_running;
++      atomic_t                wbr_wh_running;
 +#define wbr_whbase            wbr_wh[AuBrWh_BASE]     /* whiteout base */
 +#define wbr_plink             wbr_wh[AuBrWh_PLINK]    /* pseudo-link dir */
 +#define wbr_orph              wbr_wh[AuBrWh_ORPH]     /* dir for orphans */
@@ -1222,9 +1257,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.h linux-2.6.31/fs/aufs/branch.h
 +              ? -EROFS : 0;
 +}
 +
-+static inline int au_br_hinotifyable(int brperm __maybe_unused)
++static inline int au_br_hnotifyable(int brperm __maybe_unused)
 +{
-+#ifdef CONFIG_AUFS_HINOTIFY
++#ifdef CONFIG_AUFS_HNOTIFY
 +      return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
 +#else
 +      return 0;
@@ -1322,12 +1357,49 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/branch.h linux-2.6.31/fs/aufs/branch.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_BRANCH_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
---- linux-2.6.31-vanilla/fs/aufs/cpup.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/cpup.c        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,1048 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/conf.mk linux-2.6.33.1/fs/aufs/conf.mk
+--- linux-2.6.33.1-vanilla/fs/aufs/conf.mk     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/conf.mk     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,33 @@
++
++AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
++
++define AuConf
++ifdef ${1}
++AuConfStr += ${1}=${${1}}
++endif
++endef
++
++$(foreach i, BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
++      HNOTIFY HFSNOTIFY HINOTIFY \
++      EXPORT INO_T_64 \
++      RDU \
++      SP_IATTR \
++      SHWH \
++      BR_RAMFS \
++      BR_FUSE POLL \
++      BR_HFSPLUS \
++      BDEV_LOOP \
++      DEBUG MAGIC_SYSRQ, \
++      $(eval $(call AuConf,CONFIG_AUFS_${i})))
++
++AuConfName = ${obj}/conf.str
++${AuConfName}.tmp: FORCE
++      @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
++${AuConfName}: ${AuConfName}.tmp
++      @diff -q $< $@ > /dev/null 2>&1 || { \
++      echo '  GEN    ' $@; \
++      cp -p $< $@; \
++      }
++FORCE:
++clean-files += ${AuConfName} ${AuConfName}.tmp
++${obj}/sysfs.o: ${AuConfName}
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/cpup.c linux-2.6.33.1/fs/aufs/cpup.c
+--- linux-2.6.33.1-vanilla/fs/aufs/cpup.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/cpup.c      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,1049 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -1370,7 +1442,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +
 +      h_inode = au_h_iptr(inode, au_ibstart(inode));
 +      fsstack_copy_attr_times(inode, h_inode);
-+      vfsub_copy_inode_size(inode, h_inode);
++      fsstack_copy_inode_size(inode, h_inode);
 +}
 +
 +void au_cpup_attr_nlink(struct inode *inode, int force)
@@ -1469,7 +1541,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +
 +      err = vfsub_notify_change(&dt->dt_h_path, &attr);
 +      if (unlikely(err))
-+              AuWarn("restoring timestamps failed(%d). ignored\n", err);
++              pr_warning("restoring timestamps failed(%d). ignored\n", err);
 +}
 +
 +/* ---------------------------------------------------------------------- */
@@ -1744,7 +1816,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +              goto out;
 +
 +      err = -ENOMEM;
-+      sym = __getname();
++      sym = __getname_gfp(GFP_NOFS);
 +      if (unlikely(!sym))
 +              goto out;
 +
@@ -2175,7 +2247,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +
 +      dget(wh_dentry);
 +      h_path.dentry = wh_dentry;
-+      err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
++      if (!S_ISDIR(wh_dentry->d_inode->i_mode))
++              err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
++      else
++              err = vfsub_rmdir(h_parent->d_inode, &h_path);
 +      if (unlikely(err)) {
 +              AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
 +                      AuDLNPair(wh_dentry), err);
@@ -2224,10 +2299,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +              h_orph = wbr->wbr_orph;
 +
 +              h_parent = dget(au_h_dptr(parent, bdst));
-+              au_set_h_dptr(parent, bdst, NULL);
 +              au_set_h_dptr(parent, bdst, dget(h_orph));
 +              h_tmpdir = h_orph->d_inode;
-+              au_set_h_iptr(dir, bdst, NULL, 0);
 +              au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
 +
 +              /* this temporary unlock is safe */
@@ -2240,6 +2313,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +              mutex_unlock(&h_inode->i_mutex);
 +              mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
 +              mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++              /* todo: au_h_open_pre()? */
 +      }
 +
 +      if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
@@ -2259,9 +2333,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +
 +      if (h_orph) {
 +              mutex_unlock(&h_tmpdir->i_mutex);
-+              au_set_h_iptr(dir, bdst, NULL, 0);
++              /* todo: au_h_open_post()? */
 +              au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
-+              au_set_h_dptr(parent, bdst, NULL);
 +              au_set_h_dptr(parent, bdst, h_parent);
 +      }
 +      iput(h_dir);
@@ -2374,12 +2447,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.c linux-2.6.31/fs/aufs/cpup.c
 +      dput(parent);
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.h linux-2.6.31/fs/aufs/cpup.h
---- linux-2.6.31-vanilla/fs/aufs/cpup.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/cpup.h        2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/cpup.h linux-2.6.33.1/fs/aufs/cpup.h
+--- linux-2.6.33.1-vanilla/fs/aufs/cpup.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/cpup.h      2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,81 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -2459,12 +2532,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/cpup.h linux-2.6.31/fs/aufs/cpup.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_CPUP_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dbgaufs.c linux-2.6.31/fs/aufs/dbgaufs.c
---- linux-2.6.31-vanilla/fs/aufs/dbgaufs.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dbgaufs.c     2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.c linux-2.6.33.1/fs/aufs/dbgaufs.c
+--- linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dbgaufs.c   2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,331 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -2794,12 +2867,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dbgaufs.c linux-2.6.31/fs/aufs/dbgaufs.c
 +              err = 0;
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dbgaufs.h linux-2.6.31/fs/aufs/dbgaufs.h
---- linux-2.6.31-vanilla/fs/aufs/dbgaufs.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dbgaufs.h     2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,79 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.h linux-2.6.33.1/fs/aufs/dbgaufs.h
+--- linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dbgaufs.h   2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,52 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -2839,50 +2912,23 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dbgaufs.h linux-2.6.31/fs/aufs/dbgaufs.h
 +int dbgaufs_si_init(struct au_sbinfo *sbinfo);
 +void dbgaufs_fin(void);
 +int __init dbgaufs_init(void);
-+
 +#else
-+
-+static inline
-+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+      /* empty */
-+}
-+
-+static inline
-+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+      /* empty */
-+}
-+
-+static inline
-+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
-+{
-+      /* empty */
-+}
-+
-+static inline
-+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
-+{
-+      return 0;
-+}
-+
-+#define dbgaufs_fin() do {} while (0)
-+
-+static inline
-+int __init dbgaufs_init(void)
-+{
-+      return 0;
-+}
++AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
++AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
++AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
++AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
++AuStubVoid(dbgaufs_fin, void)
++AuStubInt0(__init dbgaufs_init, void)
 +#endif /* CONFIG_DEBUG_FS */
 +
 +#endif /* __KERNEL__ */
 +#endif /* __DBGAUFS_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dcsub.c linux-2.6.31/fs/aufs/dcsub.c
---- linux-2.6.31-vanilla/fs/aufs/dcsub.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dcsub.c       2009-09-16 13:55:29.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dcsub.c linux-2.6.33.1/fs/aufs/dcsub.c
+--- linux-2.6.33.1-vanilla/fs/aufs/dcsub.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dcsub.c     2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,223 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -3104,12 +3150,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dcsub.c linux-2.6.31/fs/aufs/dcsub.c
 + out:
 +      return trap;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dcsub.h linux-2.6.31/fs/aufs/dcsub.h
---- linux-2.6.31-vanilla/fs/aufs/dcsub.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dcsub.h       2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dcsub.h linux-2.6.33.1/fs/aufs/dcsub.h
+--- linux-2.6.33.1-vanilla/fs/aufs/dcsub.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dcsub.h     2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,54 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -3162,12 +3208,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dcsub.h linux-2.6.31/fs/aufs/dcsub.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_DCSUB_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.c linux-2.6.31/fs/aufs/debug.c
---- linux-2.6.31-vanilla/fs/aufs/debug.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/debug.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,431 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/debug.c linux-2.6.33.1/fs/aufs/debug.c
+--- linux-2.6.33.1-vanilla/fs/aufs/debug.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/debug.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,432 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -3197,9 +3243,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.c linux-2.6.31/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, arg...) do { \
++#define dpri(fmt, ...) do { \
 +      if (au_debug_test()) \
-+              printk("%s" fmt, au_plevel, ##arg); \
++              printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
 +} while (0)
 +
 +/* ---------------------------------------------------------------------- */
@@ -3356,7 +3402,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.c linux-2.6.31/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_test_mmapped(file));
++              snprintf(a, sizeof(a), ", mmapped %d",
++                       !!au_fi(file)->fi_h_vm_ops);
 +      dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
 +           bindex, file->f_mode, file->f_flags, (long)file_count(file),
 +           file->f_pos, a);
@@ -3567,8 +3614,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.c linux-2.6.31/fs/aufs/debug.c
 +#ifdef AuForceNoRefrof
 +      au_opt_clr(sbinfo->si_mntflags, REFROF);
 +#endif
-+#ifdef AuForceHinotify
-+      au_opt_set_udba(sbinfo->si_mntflags, UDBA_HINOTIFY);
++#ifdef AuForceHnotify
++      au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
 +#endif
 +#ifdef AuForceRd0
 +      sbinfo->si_rdblk = 0;
@@ -3588,7 +3635,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.c linux-2.6.31/fs/aufs/debug.c
 +      AuDebugOn(destr.len < NAME_MAX);
 +
 +#ifdef CONFIG_4KSTACKS
-+      AuWarn("CONFIG_4KSTACKS is defined.\n");
++      pr_warning("CONFIG_4KSTACKS is defined.\n");
 +#endif
 +
 +#ifdef AuForceNoBrs
@@ -3597,12 +3644,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.c linux-2.6.31/fs/aufs/debug.c
 +
 +      return 0;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.h linux-2.6.31/fs/aufs/debug.h
---- linux-2.6.31-vanilla/fs/aufs/debug.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/debug.h       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,263 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/debug.h linux-2.6.33.1/fs/aufs/debug.h
+--- linux-2.6.33.1-vanilla/fs/aufs/debug.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/debug.h     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,229 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -3658,51 +3705,42 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.h linux-2.6.31/fs/aufs/debug.h
 +}
 +#else
 +#define AuDebugOn(a)          do {} while (0)
-+#define au_debug()            do {} while (0)
-+static inline int au_debug_test(void)
-+{
-+      return 0;
-+}
++AuStubVoid(au_debug, int n)
++AuStubInt0(au_debug_test, void)
 +#endif /* CONFIG_AUFS_DEBUG */
 +
 +/* ---------------------------------------------------------------------- */
 +
 +/* debug print */
 +
-+#define AuDpri(lvl, fmt, arg...) \
-+      printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
-+             __func__, __LINE__, current->comm, current->pid, ##arg)
-+#define AuDbg(fmt, arg...) do { \
++#define AuDbg(fmt, ...) do { \
 +      if (au_debug_test()) \
-+              AuDpri(KERN_DEBUG, "DEBUG: " fmt, ##arg); \
++              pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
 +} while (0)
-+#define AuLabel(l)            AuDbg(#l "\n")
-+#define AuInfo(fmt, arg...)   AuDpri(KERN_INFO, fmt, ##arg)
-+#define AuWarn(fmt, arg...)   AuDpri(KERN_WARNING, fmt, ##arg)
-+#define AuErr(fmt, arg...)    AuDpri(KERN_ERR, fmt, ##arg)
-+#define AuIOErr(fmt, arg...)  AuErr("I/O Error, " fmt, ##arg)
-+#define AuWarn1(fmt, arg...) do { \
++#define AuLabel(l)            AuDbg(#l "\n")
++#define AuIOErr(fmt, ...)     pr_err("I/O Error, " fmt, ##__VA_ARGS__)
++#define AuWarn1(fmt, ...) do { \
 +      static unsigned char _c; \
 +      if (!_c++) \
-+              AuWarn(fmt, ##arg); \
++              pr_warning(fmt, ##__VA_ARGS__); \
 +} while (0)
 +
-+#define AuErr1(fmt, arg...) do { \
++#define AuErr1(fmt, ...) do { \
 +      static unsigned char _c; \
 +      if (!_c++) \
-+              AuErr(fmt, ##arg); \
++              pr_err(fmt, ##__VA_ARGS__); \
 +} while (0)
 +
-+#define AuIOErr1(fmt, arg...) do { \
++#define AuIOErr1(fmt, ...) do { \
 +      static unsigned char _c; \
 +      if (!_c++) \
-+              AuIOErr(fmt, ##arg); \
++              AuIOErr(fmt, ##__VA_ARGS__); \
 +} while (0)
 +
 +#define AuUnsupportMsg        "This operation is not supported." \
 +                      " Please report this application to aufs-users ML."
-+#define AuUnsupport(fmt, args...) do { \
-+      AuErr(AuUnsupportMsg "\n" fmt, ##args); \
++#define AuUnsupport(fmt, ...) do { \
++      pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
 +      dump_stack(); \
 +} while (0)
 +
@@ -3796,37 +3834,15 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.h linux-2.6.31/fs/aufs/debug.h
 +      au_dbg_iattr(ia); \
 +} while (0)
 +#else
-+static inline void au_dbg_verify_dir_parent(struct dentry *dentry,
-+                                          unsigned int sigen)
-+{
-+      /* empty */
-+}
-+static inline void au_dbg_verify_nondir_parent(struct dentry *dentry,
-+                                             unsigned int sigen)
-+{
-+      /* empty */
-+}
-+static inline void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
-+{
-+      /* empty */
-+}
-+static inline void au_dbg_verify_hf(struct au_finfo *finfo)
-+{
-+      /* empty */
-+}
-+static inline void au_dbg_verify_kthread(void)
-+{
-+      /* empty */
-+}
++AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
++AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
++         unsigned int sigen)
++AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
++AuStubVoid(au_dbg_verify_hf, struct au_finfo *finfo)
++AuStubVoid(au_dbg_verify_kthread, void)
++AuStubInt0(__init au_debug_init, void)
++AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
 +
-+static inline int au_debug_init(void)
-+{
-+      return 0;
-+}
-+static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
-+{
-+      /* empty */
-+}
 +#define AuDbgWhlist(w)                do {} while (0)
 +#define AuDbgVdir(v)          do {} while (0)
 +#define AuDbgInode(i)         do {} while (0)
@@ -3850,26 +3866,23 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/debug.h linux-2.6.31/fs/aufs/debug.h
 +      handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
 +} while (0)
 +#else
-+#define au_dbg_blocked()      do {} while (0)
++AuStubVoid(au_dbg_blocked, void)
 +#endif
 +
 +#else
-+static inline int au_sysrq_init(void)
-+{
-+      return 0;
-+}
-+#define au_sysrq_fin()                do {} while (0)
-+#define au_dbg_blocked()      do {} while (0)
++AuStubInt0(__init au_sysrq_init, void)
++AuStubVoid(au_sysrq_fin, void)
++AuStubVoid(au_dbg_blocked, void)
 +#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_DEBUG_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
---- linux-2.6.31-vanilla/fs/aufs/dentry.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dentry.c      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,879 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dentry.c linux-2.6.33.1/fs/aufs/dentry.c
+--- linux-2.6.33.1-vanilla/fs/aufs/dentry.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dentry.c    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,874 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -3940,6 +3953,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +              path_put(&h_nd.path);
 +      }
 +
++      AuTraceErrPtr(h_dentry);
 +      return h_dentry;
 +}
 +
@@ -3971,13 +3985,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +{
 +      struct dentry *h_dentry;
 +      struct inode *h_inode, *inode;
-+      struct qstr *name;
 +      struct au_branch *br;
 +      int wh_found, opq;
 +      unsigned char wh_able;
 +      const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
 +
-+      name = &dentry->d_name;
 +      wh_found = 0;
 +      br = au_sbr(dentry->d_sb, bindex);
 +      wh_able = !!au_br_whable(br->br_perm);
@@ -3996,7 +4008,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +              return NULL; /* success */
 +
 + real_lookup:
-+      h_dentry = au_lkup_one(name, h_parent, br, args->nd);
++      h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
 +      if (IS_ERR(h_dentry))
 +              goto out;
 +
@@ -4066,7 +4078,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +      struct dentry *parent;
 +      struct inode *inode;
 +
-+      parent = dget_parent(dentry);
 +      err = au_test_shwh(dentry->d_sb, name);
 +      if (unlikely(err))
 +              goto out;
@@ -4081,6 +4092,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +              au_fset_lkup(args.flags, ALLOW_NEG);
 +
 +      npositive = 0;
++      parent = dget_parent(dentry);
 +      btail = au_dbtaildir(parent);
 +      for (bindex = bstart; bindex <= btail; bindex++) {
 +              struct dentry *h_parent, *h_dentry;
@@ -4107,7 +4119,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +              mutex_unlock(&h_dir->i_mutex);
 +              err = PTR_ERR(h_dentry);
 +              if (IS_ERR(h_dentry))
-+                      goto out_wh;
++                      goto out_parent;
 +              au_fclr_lkup(args.flags, ALLOW_NEG);
 +
 +              if (au_dbwh(dentry) >= 0)
@@ -4140,10 +4152,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +              /* both of real entry and whiteout found */
 +              err = -EIO;
 +
-+ out_wh:
++ out_parent:
++      dput(parent);
 +      kfree(whname.name);
 + out:
-+      dput(parent);
 +      return err;
 +}
 +
@@ -4179,12 +4191,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +{
 +      int err;
 +      struct dentry *parent, *h_parent, *h_dentry;
-+      struct qstr *name;
 +
-+      name = &dentry->d_name;
 +      parent = dget_parent(dentry);
 +      h_parent = au_h_dptr(parent, bindex);
-+      h_dentry = au_sio_lkup_one(name, h_parent,
++      h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
 +                                 au_sbr(dentry->d_sb, bindex));
 +      err = PTR_ERR(h_dentry);
 +      if (IS_ERR(h_dentry))
@@ -4197,12 +4207,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +              goto out;
 +      }
 +
++      err = 0;
 +      if (bindex < au_dbstart(dentry))
 +              au_set_dbstart(dentry, bindex);
 +      if (au_dbend(dentry) < bindex)
 +              au_set_dbend(dentry, bindex);
 +      au_set_h_dptr(dentry, bindex, h_dentry);
-+      err = 0;
 +
 + out:
 +      dput(parent);
@@ -4300,7 +4310,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +      if (udba == AuOpt_UDBA_REVAL) {
 +              IMustLock(h_dir);
 +              err = (h_dentry->d_parent->d_inode != h_dir);
-+      } else if (udba == AuOpt_UDBA_HINOTIFY)
++      } else if (udba == AuOpt_UDBA_HNOTIFY)
 +              err = au_h_verify_dentry(h_dentry, h_parent, br);
 +
 +      return err;
@@ -4488,14 +4498,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +      umode_t mode, h_mode;
 +      aufs_bindex_t bindex, btail, bstart, ibs, ibe;
 +      unsigned char plus, unhashed, is_root, h_plus;
-+      struct inode *first, *h_inode, *h_cached_inode;
++      struct inode *h_inode, *h_cached_inode;
 +      struct dentry *h_dentry;
 +      struct qstr *name, *h_name;
 +
 +      err = 0;
 +      plus = 0;
 +      mode = 0;
-+      first = NULL;
 +      ibs = -1;
 +      ibe = -1;
 +      unhashed = !!d_unhashed(dentry);
@@ -4512,7 +4521,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +      if (do_udba && inode) {
 +              mode = (inode->i_mode & S_IFMT);
 +              plus = (inode->i_nlink > 0);
-+              first = au_h_iptr(inode, au_ibstart(inode));
 +              ibs = au_ibstart(inode);
 +              ibe = au_ibend(inode);
 +      }
@@ -4740,19 +4748,19 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.c linux-2.6.31/fs/aufs/dentry.c
 +      kfree(dinfo->di_hdentry);
 +      AuRwDestroy(&dinfo->di_rwsem);
 +      au_cache_free_dinfo(dinfo);
-+      au_hin_di_reinit(dentry);
++      au_hn_di_reinit(dentry);
 +}
 +
-+struct dentry_operations aufs_dop = {
++const struct dentry_operations aufs_dop = {
 +      .d_revalidate   = aufs_d_revalidate,
 +      .d_release      = aufs_d_release
 +};
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.h linux-2.6.31/fs/aufs/dentry.h
---- linux-2.6.31-vanilla/fs/aufs/dentry.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dentry.h      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,231 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dentry.h linux-2.6.33.1/fs/aufs/dentry.h
+--- linux-2.6.33.1-vanilla/fs/aufs/dentry.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dentry.h    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,228 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -4799,7 +4807,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.h linux-2.6.31/fs/aufs/dentry.h
 +/* ---------------------------------------------------------------------- */
 +
 +/* dentry.c */
-+extern struct dentry_operations aufs_dop;
++extern const struct dentry_operations aufs_dop;
 +struct au_branch;
 +struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
 +                         struct au_branch *br, struct nameidata *nd);
@@ -4851,7 +4859,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.h linux-2.6.31/fs/aufs/dentry.h
 +/* lock subclass for dinfo */
 +enum {
 +      AuLsc_DI_CHILD,         /* child first */
-+      AuLsc_DI_CHILD2,        /* rename(2), link(2), and cpup at hinotify */
++      AuLsc_DI_CHILD2,        /* rename(2), link(2), and cpup at hnotify */
 +      AuLsc_DI_CHILD3,        /* copyup dirs */
 +      AuLsc_DI_PARENT,
 +      AuLsc_DI_PARENT2,
@@ -4963,31 +4971,28 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dentry.h linux-2.6.31/fs/aufs/dentry.h
 +
 +/* ---------------------------------------------------------------------- */
 +
-+#ifdef CONFIG_AUFS_HINOTIFY
++#ifdef CONFIG_AUFS_HNOTIFY
 +static inline void au_digen_dec(struct dentry *d)
 +{
 +      atomic_dec_return(&au_di(d)->di_generation);
 +}
 +
-+static inline void au_hin_di_reinit(struct dentry *dentry)
++static inline void au_hn_di_reinit(struct dentry *dentry)
 +{
 +      dentry->d_fsdata = NULL;
 +}
 +#else
-+static inline void au_hin_di_reinit(struct dentry *dentry __maybe_unused)
-+{
-+      /* empty */
-+}
-+#endif /* CONFIG_AUFS_HINOTIFY */
++AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
++#endif /* CONFIG_AUFS_HNOTIFY */
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_DENTRY_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dinfo.c linux-2.6.31/fs/aufs/dinfo.c
---- linux-2.6.31-vanilla/fs/aufs/dinfo.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dinfo.c       2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dinfo.c linux-2.6.33.1/fs/aufs/dinfo.c
+--- linux-2.6.33.1-vanilla/fs/aufs/dinfo.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dinfo.c     2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,367 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -5353,12 +5358,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dinfo.c linux-2.6.31/fs/aufs/dinfo.c
 +                      return bindex;
 +      return -1;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.c linux-2.6.31/fs/aufs/dir.c
---- linux-2.6.31-vanilla/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dir.c 2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,593 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dir.c linux-2.6.33.1/fs/aufs/dir.c
+--- linux-2.6.33.1-vanilla/fs/aufs/dir.c       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dir.c       2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,579 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -5471,9 +5476,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.c linux-2.6.31/fs/aufs/dir.c
 +              au_set_h_fptr(file, bindex, NULL);
 +      au_set_fbend(file, btail);
 +
-+      spin_lock(&file->f_lock);
-+      flags = file->f_flags;
-+      spin_unlock(&file->f_lock);
++      flags = vfsub_file_flags(file);
 +      for (bindex = bstart; bindex <= btail; bindex++) {
 +              h_dentry = au_h_dptr(dentry, bindex);
 +              if (!h_dentry)
@@ -5509,7 +5512,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.c linux-2.6.31/fs/aufs/dir.c
 +      err = 0;
 +      dentry = file->f_dentry;
 +      au_set_fvdir_cache(file, NULL);
-+      au_fi(file)->fi_maintain_plink = 0;
 +      file->f_version = dentry->d_inode->i_version;
 +      bindex = au_dbstart(dentry);
 +      au_set_fbstart(file, bindex);
@@ -5552,24 +5554,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.c linux-2.6.31/fs/aufs/dir.c
 +{
 +      struct au_vdir *vdir_cache;
 +      struct super_block *sb;
-+      struct au_sbinfo *sbinfo;
 +
 +      sb = file->f_dentry->d_sb;
-+      si_noflush_read_lock(sb);
-+      fi_write_lock(file);
-+      vdir_cache = au_fvdir_cache(file);
++      vdir_cache = au_fi(file)->fi_vdir_cache; /* lock-free */
 +      if (vdir_cache)
 +              au_vdir_free(vdir_cache);
-+      if (au_fi(file)->fi_maintain_plink) {
-+              sbinfo = au_sbi(sb);
-+              /* clear the flag without write-lock */
-+              sbinfo->au_si_status &= ~AuSi_MAINTAIN_PLINK;
-+              smp_mb();
-+              wake_up_all(&sbinfo->si_plink_wq);
-+      }
-+      fi_write_unlock(file);
++      au_plink_maint_leave(file);
 +      au_finfo_fin(file);
-+      si_read_unlock(sb);
 +      return 0;
 +}
 +
@@ -5720,9 +5711,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.c linux-2.6.31/fs/aufs/dir.c
 +
 +              di_read_unlock(dentry, AuLock_IR);
 +              si_read_unlock(sb);
-+              lockdep_off();
++              /* lockdep_off(); */
 +              err = au_vdir_fill_de(file, dirent, filldir);
-+              lockdep_on();
++              /* lockdep_on(); */
 +              fsstack_copy_attr_atime(inode, h_inode);
 +              fi_write_unlock(file);
 +
@@ -5950,12 +5941,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.c linux-2.6.31/fs/aufs/dir.c
 +      .flush          = aufs_flush,
 +      .fsync          = aufs_fsync_dir
 +};
-diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.h linux-2.6.31/fs/aufs/dir.h
---- linux-2.6.31-vanilla/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/dir.h 2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dir.h linux-2.6.33.1/fs/aufs/dir.h
+--- linux-2.6.33.1-vanilla/fs/aufs/dir.h       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/dir.h       2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,127 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -6081,12 +6072,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/dir.h linux-2.6.31/fs/aufs/dir.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_DIR_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/export.c linux-2.6.31/fs/aufs/export.c
---- linux-2.6.31-vanilla/fs/aufs/export.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/export.c      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,746 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/export.c linux-2.6.33.1/fs/aufs/export.c
+--- linux-2.6.33.1-vanilla/fs/aufs/export.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/export.c    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,745 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -6434,14 +6425,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/export.c linux-2.6.31/fs/aufs/export.c
 +      parent = path->dentry;
 +      if (nsi_lock)
 +              si_read_unlock(parent->d_sb);
-+      path_get(path);
-+      file = vfsub_dentry_open(path, au_dir_roflags, current_cred());
++      file = vfsub_dentry_open(path, au_dir_roflags);
 +      dentry = (void *)file;
 +      if (IS_ERR(file))
 +              goto out;
 +
 +      dentry = ERR_PTR(-ENOMEM);
-+      arg.name = __getname();
++      arg.name = __getname_gfp(GFP_NOFS);
 +      if (unlikely(!arg.name))
 +              goto out_file;
 +      arg.ino = ino;
@@ -6831,12 +6821,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/export.c linux-2.6.31/fs/aufs/export.c
 +      BUILD_BUG_ON(sizeof(u) != sizeof(int));
 +      atomic_set(&sbinfo->si_xigen_next, u);
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
---- linux-2.6.31-vanilla/fs/aufs/file.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/file.c        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,568 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/file.c linux-2.6.33.1/fs/aufs/file.c
+--- linux-2.6.33.1-vanilla/fs/aufs/file.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/file.c      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,606 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -6880,8 +6870,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +      struct inode *h_inode;
 +      struct super_block *sb;
 +      struct au_branch *br;
-+      int err, exec_flag;
 +      struct path h_path;
++      int err, exec_flag;
 +
 +      /* a race condition can happen between open and unlink/rmdir */
 +      h_file = ERR_PTR(-ENOENT);
@@ -6909,8 +6899,18 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +      atomic_inc(&br->br_count);
 +      h_path.dentry = h_dentry;
 +      h_path.mnt = br->br_mnt;
-+      path_get(&h_path);
-+      h_file = vfsub_dentry_open(&h_path, flags, current_cred());
++      if (!au_special_file(h_inode->i_mode))
++              h_file = vfsub_dentry_open(&h_path, flags);
++      else {
++              /* this block depends upon the configuration */
++              di_read_unlock(dentry, AuLock_IR);
++              fi_write_unlock(file);
++              si_read_unlock(sb);
++              h_file = vfsub_dentry_open(&h_path, flags);
++              si_noflush_read_lock(sb);
++              fi_write_lock(file);
++              di_read_lock_child(dentry, AuLock_IR);
++      }
 +      if (IS_ERR(h_file))
 +              goto out_br;
 +
@@ -6934,7 +6934,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
 +{
 +      int err;
-+      unsigned int flags;
 +      struct dentry *dentry;
 +      struct super_block *sb;
 +
@@ -6946,10 +6945,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +              goto out;
 +
 +      di_read_lock_child(dentry, AuLock_IR);
-+      spin_lock(&file->f_lock);
-+      flags = file->f_flags;
-+      spin_unlock(&file->f_lock);
-+      err = open(file, flags);
++      err = open(file, vfsub_file_flags(file));
 +      di_read_unlock(dentry, AuLock_IR);
 +
 +      fi_write_unlock(file);
@@ -6963,12 +6959,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +int au_reopen_nondir(struct file *file)
 +{
 +      int err;
-+      unsigned int flags;
 +      aufs_bindex_t bstart, bindex, bend;
 +      struct dentry *dentry;
 +      struct file *h_file, *h_file_tmp;
 +
 +      dentry = file->f_dentry;
++      AuDebugOn(au_special_file(dentry->d_inode->i_mode));
 +      bstart = au_dbstart(dentry);
 +      h_file_tmp = NULL;
 +      if (au_fbstart(file) == bstart) {
@@ -6982,10 +6978,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +      AuDebugOn(au_fbstart(file) < bstart
 +                || au_fi(file)->fi_hfile[0 + bstart].hf_file);
 +
-+      spin_lock(&file->f_lock);
-+      flags = file->f_flags & ~O_TRUNC;
-+      spin_unlock(&file->f_lock);
-+      h_file = au_h_open(dentry, bstart, flags, file);
++      h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
++                         file);
 +      err = PTR_ERR(h_file);
 +      if (IS_ERR(h_file))
 +              goto out; /* todo: close all? */
@@ -7039,9 +7033,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +      int err;
 +      struct inode *inode;
 +      struct dentry *dentry, *hi_wh;
-+      struct super_block *sb;
 +
 +      dentry = file->f_dentry;
++      au_update_dbstart(dentry);
 +      inode = dentry->d_inode;
 +      hi_wh = au_hi_wh(inode, bcpup);
 +      if (!hi_wh)
@@ -7050,8 +7044,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +              /* already copied-up after unlink */
 +              err = au_reopen_wh(file, bcpup, hi_wh);
 +
-+      sb = dentry->d_sb;
-+      if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
++      if (!err
++          && inode->i_nlink > 1
++          && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
 +              au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
 +
 +      return err;
@@ -7067,11 +7062,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +      struct dentry *dentry, *parent, *h_dentry;
 +      struct inode *h_inode, *inode;
 +      struct super_block *sb;
++      struct file *h_file;
 +
 +      dentry = file->f_dentry;
 +      sb = dentry->d_sb;
-+      bstart = au_fbstart(file);
 +      inode = dentry->d_inode;
++      AuDebugOn(au_special_file(inode->i_mode));
++      bstart = au_fbstart(file);
 +      err = au_test_ro(sb, bstart, inode);
 +      if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
 +              err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
@@ -7101,7 +7098,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +      h_dentry = au_h_fptr(file, bstart)->f_dentry;
 +      h_inode = h_dentry->d_inode;
 +      mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+      if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
++      h_file = au_h_open_pre(dentry, bstart);
++      if (IS_ERR(h_file)) {
++              err = PTR_ERR(h_file);
++              h_file = NULL;
++      } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
 +          /* || !h_inode->i_nlink */) {
 +              err = au_ready_to_write_wh(file, len, bcpup);
 +              di_downgrade_lock(parent, AuLock_IR);
@@ -7114,6 +7115,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +                      err = au_reopen_nondir(file);
 +      }
 +      mutex_unlock(&h_inode->i_mutex);
++      au_h_open_post(dentry, bstart, h_file);
 +
 +      if (!err) {
 +              au_pin_set_parent_lflag(pin, /*lflag*/0);
@@ -7311,15 +7313,18 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +      aufs_bindex_t bstart;
 +      unsigned char pseudo_link;
 +      struct dentry *dentry;
++      struct inode *inode;
 +
 +      err = 0;
 +      dentry = file->f_dentry;
++      inode = dentry->d_inode;
++      AuDebugOn(au_special_file(inode->i_mode));
 +      sigen = au_sigen(dentry->d_sb);
 +      fi_write_lock(file);
 +      figen = au_figen(file);
 +      di_write_lock_child(dentry);
 +      bstart = au_dbstart(dentry);
-+      pseudo_link = (bstart != au_ibstart(dentry->d_inode));
++      pseudo_link = (bstart != au_ibstart(inode));
 +      if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
 +              if (!wlock) {
 +                      di_downgrade_lock(dentry, AuLock_IR);
@@ -7330,12 +7335,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +
 +      AuDbg("sigen %d, figen %d\n", sigen, figen);
 +      if (sigen != au_digen(dentry)
-+          || sigen != au_iigen(dentry->d_inode)) {
++          || sigen != au_iigen(inode)) {
 +              err = au_reval_dpath(dentry, sigen);
 +              if (unlikely(err < 0))
 +                      goto out;
 +              AuDebugOn(au_digen(dentry) != sigen
-+                        || au_iigen(dentry->d_inode) != sigen);
++                        || au_iigen(inode) != sigen);
 +      }
 +
 +      err = refresh_file(file, reopen);
@@ -7388,27 +7393,50 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.c linux-2.6.31/fs/aufs/file.c
 +                            const struct iovec *iov, loff_t offset,
 +                            unsigned long nr_segs)
 +{ AuUnsupport(); return 0; }
++static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
++                          int create, void **kmem, unsigned long *pfn)
++{ AuUnsupport(); return 0; }
++static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
++                          struct page *page)
++{ AuUnsupport(); return 0; }
++static int aufs_launder_page(struct page *page)
++{ AuUnsupport(); return 0; }
++static int aufs_is_partially_uptodate(struct page *page,
++                                    read_descriptor_t *desc,
++                                    unsigned long from)
++{ AuUnsupport(); return 0; }
++static int aufs_error_remove_page(struct address_space *mapping,
++                                struct page *page)
++{ AuUnsupport(); return 0; }
 +#endif /* CONFIG_AUFS_DEBUG */
 +
-+struct address_space_operations aufs_aop = {
-+      .readpage       = aufs_readpage,
++const struct address_space_operations aufs_aop = {
++      .readpage               = aufs_readpage,
 +#ifdef CONFIG_AUFS_DEBUG
-+      .writepage      = aufs_writepage,
-+      .sync_page      = aufs_sync_page,
-+      .set_page_dirty = aufs_set_page_dirty,
-+      .write_begin    = aufs_write_begin,
-+      .write_end      = aufs_write_end,
-+      .invalidatepage = aufs_invalidatepage,
-+      .releasepage    = aufs_releasepage,
-+      .direct_IO      = aufs_direct_IO,
++      .writepage              = aufs_writepage,
++      .sync_page              = aufs_sync_page,
++      /* no writepages, because of writepage */
++      .set_page_dirty         = aufs_set_page_dirty,
++      /* no readpages, because of readpage */
++      .write_begin            = aufs_write_begin,
++      .write_end              = aufs_write_end,
++      /* no bmap, no block device */
++      .invalidatepage         = aufs_invalidatepage,
++      .releasepage            = aufs_releasepage,
++      .direct_IO              = aufs_direct_IO,       /* todo */
++      .get_xip_mem            = aufs_get_xip_mem,     /* todo */
++      .migratepage            = aufs_migratepage,
++      .launder_page           = aufs_launder_page,
++      .is_partially_uptodate  = aufs_is_partially_uptodate,
++      .error_remove_page      = aufs_error_remove_page
 +#endif /* CONFIG_AUFS_DEBUG */
 +};
-diff -Nur linux-2.6.31-vanilla/fs/aufs/file.h linux-2.6.31/fs/aufs/file.h
---- linux-2.6.31-vanilla/fs/aufs/file.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/file.h        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,174 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/file.h linux-2.6.33.1/fs/aufs/file.h
+--- linux-2.6.33.1-vanilla/fs/aufs/file.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/file.h      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,211 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -7458,12 +7486,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.h linux-2.6.31/fs/aufs/file.h
 +              struct {
 +                      struct vm_operations_struct     *fi_h_vm_ops;
 +                      struct vm_operations_struct     *fi_vm_ops;
++                      struct mutex                    fi_vm_mtx;
++                      struct mutex                    fi_mmap;
 +              };
 +
 +              /* dir only */
 +              struct {
 +                      struct au_vdir          *fi_vdir_cache;
-+                      int                     fi_maintain_plink;
 +              };
 +      };
 +};
@@ -7471,7 +7500,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.h linux-2.6.31/fs/aufs/file.h
 +/* ---------------------------------------------------------------------- */
 +
 +/* file.c */
-+extern struct address_space_operations aufs_aop;
++extern const struct address_space_operations aufs_aop;
 +unsigned int au_file_roflags(unsigned int flags);
 +struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
 +                     struct file *file);
@@ -7487,9 +7516,40 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.h linux-2.6.31/fs/aufs/file.h
 +unsigned int aufs_poll(struct file *file, poll_table *wait);
 +#endif
 +
++#ifdef CONFIG_AUFS_BR_HFSPLUS
++/* hfsplus.c */
++struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
++void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
++                  struct file *h_file);
++#else
++static inline
++struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      return NULL;
++}
++
++AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
++         struct file *h_file);
++#endif
++
 +/* f_op.c */
 +extern const struct file_operations aufs_file_fop;
 +int aufs_flush(struct file *file, fl_owner_t id);
++int au_do_open_nondir(struct file *file, int flags);
++int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
++
++#ifdef CONFIG_AUFS_SP_IATTR
++/* f_op_sp.c */
++int au_special_file(umode_t mode);
++void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
++#else
++AuStubInt0(au_special_file, umode_t mode)
++static inline void au_init_special_fop(struct inode *inode, umode_t mode,
++                                     dev_t rdev)
++{
++      init_special_inode(inode, mode, rdev);
++}
++#endif
 +
 +/* finfo.c */
 +void au_hfput(struct au_hfile *hf, struct file *file);
@@ -7497,11 +7557,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.h linux-2.6.31/fs/aufs/file.h
 +                 struct file *h_file);
 +
 +void au_update_figen(struct file *file);
++void au_fi_mmap_lock(struct file *file);
++void au_fi_mmap_unlock(struct file *file);
 +
 +void au_finfo_fin(struct file *file);
 +int au_finfo_init(struct file *file);
 +int au_fi_realloc(struct au_finfo *finfo, int nbr);
 +
++/* ioctl.c */
++long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
++
 +/* ---------------------------------------------------------------------- */
 +
 +static inline struct au_finfo *au_fi(struct file *file)
@@ -7575,18 +7640,18 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/file.h linux-2.6.31/fs/aufs/file.h
 +
 +static inline int au_test_mmapped(struct file *f)
 +{
-+      /* FiMustAnyLock(f); */
++      FiMustAnyLock(f);
 +      return !!(au_fi(f)->fi_h_vm_ops);
 +}
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_FILE_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/finfo.c linux-2.6.31/fs/aufs/finfo.c
---- linux-2.6.31-vanilla/fs/aufs/finfo.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/finfo.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,128 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/finfo.c linux-2.6.33.1/fs/aufs/finfo.c
+--- linux-2.6.33.1-vanilla/fs/aufs/finfo.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/finfo.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,146 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -7612,7 +7677,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/finfo.c linux-2.6.31/fs/aufs/finfo.c
 +
 +void au_hfput(struct au_hfile *hf, struct file *file)
 +{
-+      if (file->f_flags & vfsub_fmode_to_uint(FMODE_EXEC))
++      /* todo: direct access f_flags */
++      if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
 +              allow_write_access(hf->hf_file);
 +      fput(hf->hf_file);
 +      hf->hf_file = NULL;
@@ -7629,6 +7695,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/finfo.c linux-2.6.31/fs/aufs/finfo.c
 +      if (hf->hf_file)
 +              au_hfput(hf, file);
 +      if (val) {
++              FiMustWriteLock(file);
 +              hf->hf_file = val;
 +              hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
 +      }
@@ -7642,26 +7709,42 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/finfo.c linux-2.6.31/fs/aufs/finfo.c
 +
 +/* ---------------------------------------------------------------------- */
 +
++void au_fi_mmap_lock(struct file *file)
++{
++      FiMustWriteLock(file);
++      lockdep_off();
++      mutex_lock(&au_fi(file)->fi_mmap);
++      lockdep_on();
++}
++
++void au_fi_mmap_unlock(struct file *file)
++{
++      lockdep_off();
++      mutex_unlock(&au_fi(file)->fi_mmap);
++      lockdep_on();
++}
++
++/* ---------------------------------------------------------------------- */
++
 +void au_finfo_fin(struct file *file)
 +{
 +      struct au_finfo *finfo;
 +      aufs_bindex_t bindex, bend;
 +
-+      fi_write_lock(file);
-+      bend = au_fbend(file);
-+      bindex = au_fbstart(file);
-+      if (bindex >= 0)
++      finfo = au_fi(file);
++      bindex = finfo->fi_bstart;
++      if (bindex >= 0) {
 +              /*
 +               * calls fput() instead of filp_close(),
 +               * since no dnotify or lock for the lower file.
 +               */
++              bend = finfo->fi_bend;
 +              for (; bindex <= bend; bindex++)
 +                      au_set_h_fptr(file, bindex, NULL);
++      }
 +
-+      finfo = au_fi(file);
 +      au_dbg_verify_hf(finfo);
 +      kfree(finfo->fi_hfile);
-+      fi_write_unlock(file);
 +      AuRwDestroy(&finfo->fi_rwsem);
 +      au_cache_free_finfo(finfo);
 +}
@@ -7713,12 +7796,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/finfo.c linux-2.6.31/fs/aufs/finfo.c
 +
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
---- linux-2.6.31-vanilla/fs/aufs/f_op.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/f_op.c        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,823 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/f_op.c linux-2.6.33.1/fs/aufs/f_op.c
+--- linux-2.6.33.1-vanilla/fs/aufs/f_op.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/f_op.c      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,921 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -7741,7 +7824,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +
 +#include <linux/file.h>
 +#include <linux/fs_stack.h>
-+#include <linux/ima.h>
 +#include <linux/mman.h>
 +#include <linux/mm.h>
 +#include <linux/security.h>
@@ -7782,7 +7864,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +
 +/* ---------------------------------------------------------------------- */
 +
-+static int do_open_nondir(struct file *file, int flags)
++int au_do_open_nondir(struct file *file, int flags)
 +{
 +      int err;
 +      aufs_bindex_t bindex;
@@ -7797,11 +7879,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      finfo = au_fi(file);
 +      finfo->fi_h_vm_ops = NULL;
 +      finfo->fi_vm_ops = NULL;
++      mutex_init(&finfo->fi_mmap); /* regular file only? */
 +      bindex = au_dbstart(dentry);
-+      /* O_TRUNC is processed already */
-+      BUG_ON(au_test_ro(dentry->d_sb, bindex, dentry->d_inode)
-+             && (flags & O_TRUNC));
-+
 +      h_file = au_h_open(dentry, bindex, flags, file);
 +      if (IS_ERR(h_file))
 +              err = PTR_ERR(h_file);
@@ -7819,18 +7898,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +static int aufs_open_nondir(struct inode *inode __maybe_unused,
 +                          struct file *file)
 +{
-+      return au_do_open(file, do_open_nondir);
++      AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
++            AuDLNPair(file->f_dentry), vfsub_file_flags(file),
++            file->f_mode);
++      return au_do_open(file, au_do_open_nondir);
 +}
 +
-+static int aufs_release_nondir(struct inode *inode __maybe_unused,
-+                             struct file *file)
++int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
 +{
-+      struct super_block *sb = file->f_dentry->d_sb;
-+
-+      si_noflush_read_lock(sb);
 +      kfree(au_fi(file)->fi_vm_ops);
 +      au_finfo_fin(file);
-+      si_read_unlock(sb);
 +      return 0;
 +}
 +
@@ -7907,6 +7984,34 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      return err;
 +}
 +
++static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
++                       const struct iovec *iov, unsigned long nv, loff_t pos)
++{
++      ssize_t err;
++      struct file *file;
++
++      err = security_file_permission(h_file, rw);
++      if (unlikely(err))
++              goto out;
++
++      file = kio->ki_filp;
++      if (!is_sync_kiocb(kio)) {
++              get_file(h_file);
++              fput(file);
++      }
++      kio->ki_filp = h_file;
++      if (rw == MAY_READ)
++              err = h_file->f_op->aio_read(kio, iov, nv, pos);
++      else if (rw == MAY_WRITE)
++              err = h_file->f_op->aio_write(kio, iov, nv, pos);
++      else
++              BUG();
++      /* do not restore kio->ki_filp */
++
++ out:
++      return err;
++}
++
 +static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
 +                           unsigned long nv, loff_t pos)
 +{
@@ -7926,15 +8031,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      err = -ENOSYS;
 +      h_file = au_h_fptr(file, au_fbstart(file));
 +      if (h_file->f_op && h_file->f_op->aio_read) {
-+              err = security_file_permission(h_file, MAY_READ);
-+              if (unlikely(err))
-+                      goto out_unlock;
-+              if (!is_sync_kiocb(kio)) {
-+                      get_file(h_file);
-+                      fput(file);
-+              }
-+              kio->ki_filp = h_file;
-+              err = h_file->f_op->aio_read(kio, iov, nv, pos);
++              err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
 +              /* todo: necessary? */
 +              /* file->f_ra = h_file->f_ra; */
 +              fsstack_copy_attr_atime(dentry->d_inode,
@@ -7943,9 +8040,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +              /* currently there is no such fs */
 +              WARN_ON_ONCE(h_file->f_op && h_file->f_op->read);
 +
-+ out_unlock:
 +      di_read_unlock(dentry, AuLock_IR);
 +      fi_read_unlock(file);
++
 + out:
 +      si_read_unlock(sb);
 +      return err;
@@ -7955,7 +8052,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +                            unsigned long nv, loff_t pos)
 +{
 +      ssize_t err;
-+      aufs_bindex_t bstart;
 +      struct au_pin pin;
 +      struct dentry *dentry;
 +      struct inode *inode;
@@ -7979,19 +8075,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +              goto out_unlock;
 +
 +      err = -ENOSYS;
-+      bstart = au_fbstart(file);
-+      h_file = au_h_fptr(file, bstart);
++      h_file = au_h_fptr(file, au_fbstart(file));
 +      au_unpin(&pin);
 +      if (h_file->f_op && h_file->f_op->aio_write) {
-+              err = security_file_permission(h_file, MAY_WRITE);
-+              if (unlikely(err))
-+                      goto out_unlock;
-+              if (!is_sync_kiocb(kio)) {
-+                      get_file(h_file);
-+                      fput(file);
-+              }
-+              kio->ki_filp = h_file;
-+              err = h_file->f_op->aio_write(kio, iov, nv, pos);
++              err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
 +              au_cpup_attr_timesizes(inode);
 +              inode->i_mode = h_file->f_dentry->d_inode->i_mode;
 +      } else
@@ -8116,13 +8203,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
 +      AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
 +
-+      fi_write_lock(file);
++      mutex_lock(&finfo->fi_vm_mtx);
 +      vma->vm_file = h_file;
 +      err = finfo->fi_h_vm_ops->fault(vma, vmf);
 +      /* todo: necessary? */
 +      /* file->f_ra = h_file->f_ra; */
 +      au_reset_file(vma, file);
-+      fi_write_unlock(file);
++      mutex_unlock(&finfo->fi_vm_mtx);
 +#if 0 /* def CONFIG_SMP */
 +      /* wake_up_nr(&wq, online_cpu - 1); */
 +      wake_up_all(&wq);
@@ -8146,11 +8233,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
 +      AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
 +
-+      fi_write_lock(file);
++      mutex_lock(&finfo->fi_vm_mtx);
 +      vma->vm_file = h_file;
 +      err = finfo->fi_h_vm_ops->page_mkwrite(vma, vmf);
 +      au_reset_file(vma, file);
-+      fi_write_unlock(file);
++      mutex_unlock(&finfo->fi_vm_mtx);
 +      wake_up(&wq);
 +
 +      return err;
@@ -8168,11 +8255,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
 +      AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
 +
-+      fi_write_lock(file);
++      mutex_lock(&finfo->fi_vm_mtx);
 +      vma->vm_file = h_file;
 +      finfo->fi_h_vm_ops->close(vma);
 +      au_reset_file(vma, file);
-+      fi_write_unlock(file);
++      mutex_unlock(&finfo->fi_vm_mtx);
 +      wake_up(&wq);
 +}
 +
@@ -8183,33 +8270,57 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +
 +/* ---------------------------------------------------------------------- */
 +
-+static unsigned long au_prot_conv(unsigned long flags)
-+{
-+      unsigned long prot;
++/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
++#define AuConv_VM_PROT(f, b)  _calc_vm_trans(f, VM_##b, PROT_##b)
 +
-+      prot = 0;
-+      if (flags & VM_READ)
-+              prot |= PROT_READ;
-+      if (flags & VM_WRITE)
-+              prot |= PROT_WRITE;
-+      if (flags & VM_EXEC)
-+              prot |= PROT_EXEC;
-+      return prot;
++static unsigned long au_arch_prot_conv(unsigned long flags)
++{
++      /* currently ppc64 only */
++#ifdef CONFIG_PPC64
++      /* cf. linux/arch/powerpc/include/asm/mman.h */
++      AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
++      return AuConv_VM_PROT(flags, SAO);
++#else
++      AuDebugOn(arch_calc_vm_prot_bits(-1));
++      return 0;
++#endif
 +}
 +
-+static struct vm_operations_struct *au_vm_ops(struct file *h_file,
++static unsigned long au_prot_conv(unsigned long flags)
++{
++      return AuConv_VM_PROT(flags, READ)
++              | AuConv_VM_PROT(flags, WRITE)
++              | AuConv_VM_PROT(flags, EXEC)
++              | au_arch_prot_conv(flags);
++}
++
++/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
++#define AuConv_VM_MAP(f, b)   _calc_vm_trans(f, VM_##b, MAP_##b)
++
++static unsigned long au_flag_conv(unsigned long flags)
++{
++      return AuConv_VM_MAP(flags, GROWSDOWN)
++              | AuConv_VM_MAP(flags, DENYWRITE)
++              | AuConv_VM_MAP(flags, EXECUTABLE)
++              | AuConv_VM_MAP(flags, LOCKED);
++}
++
++static struct vm_operations_struct *au_vm_ops(struct file *h_file,
 +                                            struct vm_area_struct *vma)
 +{
 +      struct vm_operations_struct *vm_ops;
++      unsigned long prot;
 +      int err;
 +
 +      vm_ops = ERR_PTR(-ENODEV);
 +      if (!h_file->f_op || !h_file->f_op->mmap)
 +              goto out;
 +
-+      err = ima_file_mmap(h_file, au_prot_conv(vma->vm_flags));
++      prot = au_prot_conv(vma->vm_flags);
++      err = security_file_mmap(h_file, /*reqprot*/prot, prot,
++                               au_flag_conv(vma->vm_flags), vma->vm_start, 0);
 +      vm_ops = ERR_PTR(err);
-+      if (err)
++      if (unlikely(err))
 +              goto out;
 +
 +      err = h_file->f_op->mmap(h_file, vma);
@@ -8217,7 +8328,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      if (unlikely(err))
 +              goto out;
 +
-+      vm_ops = vma->vm_ops;
++      /* oops, it became 'const' */
++      vm_ops = (struct vm_operations_struct *)vma->vm_ops;
 +      err = do_munmap(current->mm, vma->vm_start,
 +                      vma->vm_end - vma->vm_start);
 +      if (unlikely(err)) {
@@ -8235,7 +8347,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      int err;
 +      struct vm_operations_struct *h_ops;
 +
-+      AuRwMustAnyLock(&finfo->fi_rwsem);
++      MtxMustLock(&finfo->fi_mmap);
 +
 +      err = 0;
 +      h_ops = finfo->fi_h_vm_ops;
@@ -8261,49 +8373,116 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      return err;
 +}
 +
-+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
++/*
++ * This is another ugly approach to keep the lock order, particularly
++ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
++ * find it in git-log, if you want.
++ *
++ * native readdir: i_mutex, copy_to_user, mmap_sem
++ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
++ *
++ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
++ * acquire aufs rwsem. It introduces a circular locking dependency.
++ * To address this problem, aufs_mmap() delegates the part which requires aufs
++ * rwsem to its internal workqueue.
++ */
++
++/* very ugly approach */
++#ifdef CONFIG_DEBUG_MUTEXES
++#include <../kernel/mutex-debug.h>
++#else
++#include <../kernel/mutex.h>
++#endif
++
++struct au_mmap_pre_args {
++      /* input */
++      struct file *file;
++      struct vm_area_struct *vma;
++
++      /* output */
++      int *errp;
++      struct file *h_file;
++      int mmapped;
++};
++
++static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
++                     struct file **h_file, int *mmapped)
 +{
 +      int err;
-+      unsigned char wlock, mmapped;
++      const unsigned char wlock
++              = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
 +      struct dentry *dentry;
 +      struct super_block *sb;
-+      struct file *h_file;
-+      struct vm_operations_struct *vm_ops;
 +
 +      dentry = file->f_dentry;
-+      wlock = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
 +      sb = dentry->d_sb;
-+      si_read_lock(sb, AuLock_FLUSH);
++      si_read_lock(sb, !AuLock_FLUSH);
 +      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
 +      if (unlikely(err))
 +              goto out;
 +
-+      mmapped = !!au_test_mmapped(file);
++      *mmapped = !!au_test_mmapped(file);
 +      if (wlock) {
 +              struct au_pin pin;
 +
 +              err = au_ready_to_write(file, -1, &pin);
-+              di_downgrade_lock(dentry, AuLock_IR);
++              di_write_unlock(dentry);
 +              if (unlikely(err))
 +                      goto out_unlock;
 +              au_unpin(&pin);
 +      } else
-+              di_downgrade_lock(dentry, AuLock_IR);
++              di_write_unlock(dentry);
++      *h_file = au_h_fptr(file, au_fbstart(file));
++      get_file(*h_file);
++      au_fi_mmap_lock(file);
 +
-+      h_file = au_h_fptr(file, au_fbstart(file));
-+      if (!mmapped && au_test_fs_bad_mapping(h_file->f_dentry->d_sb)) {
++out_unlock:
++      fi_write_unlock(file);
++out:
++      si_read_unlock(sb);
++      return err;
++}
++
++static void au_call_mmap_pre(void *args)
++{
++      struct au_mmap_pre_args *a = args;
++      *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->mmapped);
++}
++
++static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++      int err, wkq_err;
++      struct au_finfo *finfo;
++      struct dentry *h_dentry;
++      struct vm_operations_struct *vm_ops;
++      struct au_mmap_pre_args args = {
++              .file           = file,
++              .vma            = vma,
++              .errp           = &err
++      };
++
++      wkq_err = au_wkq_wait(au_call_mmap_pre, &args);
++      if (unlikely(wkq_err))
++              err = wkq_err;
++      if (unlikely(err))
++              goto out;
++      finfo = au_fi(file);
++      mutex_set_owner(&finfo->fi_mmap);
++
++      h_dentry = args.h_file->f_dentry;
++      if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
 +              /*
 +               * by this assignment, f_mapping will differs from aufs inode
 +               * i_mapping.
 +               * if someone else mixes the use of f_dentry->d_inode and
 +               * f_mapping->host, then a problem may arise.
 +               */
-+              file->f_mapping = h_file->f_mapping;
++              file->f_mapping = args.h_file->f_mapping;
 +      }
 +
 +      vm_ops = NULL;
-+      if (!mmapped) {
-+              vm_ops = au_vm_ops(h_file, vma);
++      if (!args.mmapped) {
++              vm_ops = au_vm_ops(args.h_file, vma);
 +              err = PTR_ERR(vm_ops);
 +              if (IS_ERR(vm_ops))
 +                      goto out_unlock;
@@ -8321,22 +8500,23 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +              goto out_unlock;
 +
 +      vma->vm_ops = &aufs_vm_ops;
-+      /* test again */
-+      if (!au_test_mmapped(file))
-+              au_fi(file)->fi_h_vm_ops = vm_ops;
++      if (!args.mmapped) {
++              finfo->fi_h_vm_ops = vm_ops;
++              mutex_init(&finfo->fi_vm_mtx);
++      }
 +
-+      err = au_custom_vm_ops(au_fi(file), vma);
++      err = au_custom_vm_ops(finfo, vma);
 +      if (unlikely(err))
 +              goto out_unlock;
 +
-+      vfsub_file_accessed(h_file);
-+      fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++      vfsub_file_accessed(args.h_file);
++      /* 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:
-+      di_read_unlock(dentry, AuLock_IR);
-+      fi_write_unlock(file);
++      au_fi_mmap_unlock(file);
++      fput(args.h_file);
 + out:
-+      si_read_unlock(sb);
 +      return err;
 +}
 +
@@ -8525,6 +8705,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +#ifdef CONFIG_AUFS_POLL
 +      .poll           = aufs_poll,
 +#endif
++      .unlocked_ioctl = aufs_ioctl_nondir,
 +      .mmap           = aufs_mmap,
 +      .open           = aufs_open_nondir,
 +      .flush          = aufs_flush,
@@ -8540,12 +8721,306 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/f_op.c linux-2.6.31/fs/aufs/f_op.c
 +      .aio_splice_read  = aufs_aio_splice_read
 +#endif
 +};
-diff -Nur linux-2.6.31-vanilla/fs/aufs/fstype.h linux-2.6.31/fs/aufs/fstype.h
---- linux-2.6.31-vanilla/fs/aufs/fstype.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/fstype.h      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,485 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/f_op_sp.c linux-2.6.33.1/fs/aufs/f_op_sp.c
+--- linux-2.6.33.1-vanilla/fs/aufs/f_op_sp.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/f_op_sp.c   2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,290 @@
++/*
++ * Copyright (C) 2005-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
++ */
++
++/*
++ * file operations for special files.
++ * while they exist in aufs virtually,
++ * their file I/O is handled out of aufs.
++ */
++
++#include <linux/fs_stack.h>
++#include "aufs.h"
++
++static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
++                              unsigned long nv, loff_t pos)
++{
++      ssize_t err;
++      aufs_bindex_t bstart;
++      unsigned char wbr;
++      struct file *file, *h_file;
++      struct super_block *sb;
++
++      file = kio->ki_filp;
++      sb = file->f_dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      fi_read_lock(file);
++      bstart = au_fbstart(file);
++      h_file = au_h_fptr(file, bstart);
++      fi_read_unlock(file);
++      wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
++      si_read_unlock(sb);
++
++      /* do not change the file in kio */
++      AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
++      err = h_file->f_op->aio_read(kio, iov, nv, pos);
++      if (err > 0 && wbr)
++              file_accessed(h_file);
++
++      return err;
++}
++
++static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
++                               unsigned long nv, loff_t pos)
++{
++      ssize_t err;
++      aufs_bindex_t bstart;
++      unsigned char wbr;
++      struct super_block *sb;
++      struct file *file, *h_file;
++
++      file = kio->ki_filp;
++      sb = file->f_dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      fi_read_lock(file);
++      bstart = au_fbstart(file);
++      h_file = au_h_fptr(file, bstart);
++      fi_read_unlock(file);
++      wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
++      si_read_unlock(sb);
++
++      /* do not change the file in kio */
++      AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
++      err = h_file->f_op->aio_write(kio, iov, nv, pos);
++      if (err > 0 && wbr)
++              file_update_time(h_file);
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_release_sp(struct inode *inode, struct file *file)
++{
++      int err;
++      struct file *h_file;
++
++      fi_read_lock(file);
++      h_file = au_h_fptr(file, au_fbstart(file));
++      fi_read_unlock(file);
++      /* close this fifo in aufs */
++      err = h_file->f_op->release(inode, file); /* ignore */
++      aufs_release_nondir(inode, file); /* ignore */
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* currently, support only FIFO */
++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;
++      struct file_operations  fop;    /* not 'const' */
++      spinlock_t              spin;
++} au_sp_fop[AuSp_Last] = {
++      [AuSp_FIFO] = {
++              .fop    = {
++                      .open   = aufs_open_sp
++              }
++      }
++};
++
++static void au_init_fop_sp(struct file *file)
++{
++      struct au_sp_fop *p;
++      int i;
++      struct file *h_file;
++
++      p = au_sp_fop;
++      if (unlikely(!p->done)) {
++              /* initialize first time only */
++              static DEFINE_SPINLOCK(spin);
++
++              spin_lock(&spin);
++              if (!p->done) {
++                      BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
++                                   != AuSp_Last);
++                      for (i = 0; i < AuSp_Last; i++)
++                              spin_lock_init(&p[i].spin);
++                      p->done = 1;
++              }
++              spin_unlock(&spin);
++      }
++
++      switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
++      case FMODE_READ:
++              i = AuSp_FIFO_R;
++              break;
++      case FMODE_WRITE:
++              i = AuSp_FIFO_W;
++              break;
++      case FMODE_READ | FMODE_WRITE:
++              i = AuSp_FIFO_RW;
++              break;
++      default:
++              BUG();
++      }
++
++      p += i;
++      if (unlikely(!p->done)) {
++              /* initialize first time only */
++              h_file = au_h_fptr(file, au_fbstart(file));
++              spin_lock(&p->spin);
++              if (!p->done) {
++                      p->fop = *h_file->f_op;
++                      if (p->fop.aio_read)
++                              p->fop.aio_read = aufs_aio_read_sp;
++                      if (p->fop.aio_write)
++                              p->fop.aio_write = aufs_aio_write_sp;
++                      p->fop.release = aufs_release_sp;
++                      p->done = 1;
++              }
++              spin_unlock(&p->spin);
++      }
++      file->f_op = &p->fop;
++}
++
++static int au_cpup_sp(struct dentry *dentry)
++{
++      int err;
++      aufs_bindex_t bcpup;
++      struct au_pin pin;
++      struct au_wr_dir_args wr_dir_args = {
++              .force_btgt     = -1,
++              .flags          = 0
++      };
++
++      AuDbg("%.*s\n", AuDLNPair(dentry));
++
++      di_read_unlock(dentry, AuLock_IR);
++      di_write_lock_child(dentry);
++      err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
++      if (unlikely(err < 0))
++              goto out;
++      bcpup = err;
++      err = 0;
++      if (bcpup == au_dbstart(dentry))
++              goto out; /* success */
++
++      err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
++                   AuPin_MNT_WRITE);
++      if (!err) {
++              err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
++              au_unpin(&pin);
++      }
++
++ out:
++      di_downgrade_lock(dentry, AuLock_IR);
++      return err;
++}
++
++static int au_do_open_sp(struct file *file, int flags)
++{
++      int err;
++      struct dentry *dentry;
++      struct super_block *sb;
++      struct file *h_file;
++      struct inode *h_inode;
++
++      dentry = file->f_dentry;
++      AuDbg("%.*s\n", AuDLNPair(dentry));
++
++      /*
++       * try copying-up.
++       * operate on the ro branch is not an error.
++       */
++      au_cpup_sp(dentry); /* ignore */
++
++      /* prepare h_file */
++      err = au_do_open_nondir(file, vfsub_file_flags(file));
++      if (unlikely(err))
++              goto out;
++
++      sb = dentry->d_sb;
++      h_file = au_h_fptr(file, au_fbstart(file));
++      h_inode = h_file->f_dentry->d_inode;
++      di_read_unlock(dentry, AuLock_IR);
++      fi_write_unlock(file);
++      si_read_unlock(sb);
++      /* open this fifo in aufs */
++      err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
++      si_noflush_read_lock(sb);
++      fi_write_lock(file);
++      di_read_lock_child(dentry, AuLock_IR);
++      if (!err)
++              au_init_fop_sp(file);
++      else
++              au_finfo_fin(file);
++
++ out:
++      return err;
++}
++
++static int aufs_open_sp(struct inode *inode, struct file *file)
++{
++      return au_do_open(file, au_do_open_sp);
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
++{
++      init_special_inode(inode, mode, rdev);
++
++      switch (mode & S_IFMT) {
++      case S_IFIFO:
++              inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
++              /*FALLTHROUGH*/
++      case S_IFCHR:
++      case S_IFBLK:
++      case S_IFSOCK:
++              break;
++      default:
++              AuDebugOn(1);
++      }
++}
++
++int au_special_file(umode_t mode)
++{
++      int ret;
++
++      ret = 0;
++      switch (mode & S_IFMT) {
++      case S_IFIFO:
++#if 0
++      case S_IFCHR:
++      case S_IFBLK:
++      case S_IFSOCK:
++#endif
++              ret = 1;
++      }
++
++      return ret;
++}
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/fstype.h linux-2.6.33.1/fs/aufs/fstype.h
+--- linux-2.6.33.1-vanilla/fs/aufs/fstype.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/fstype.h    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,497 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -8571,7 +9046,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/fstype.h linux-2.6.31/fs/aufs/fstype.h
 +
 +#ifdef __KERNEL__
 +
-+#include <linux/cramfs_fs.h>
 +#include <linux/fs.h>
 +#include <linux/magic.h>
 +#include <linux/romfs_fs.h>
@@ -8857,7 +9331,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/fstype.h linux-2.6.31/fs/aufs/fstype.h
 +#endif
 +}
 +
-+/* ---------------------------------------------------------------------- */
++static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
++      return sb->s_magic == HFSPLUS_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
 +/*
 + * they can't be an aufs branch.
 + */
@@ -8928,11 +9411,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/fstype.h linux-2.6.31/fs/aufs/fstype.h
 +static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
 +{
 +      return au_test_xfs(sb)
++              || au_test_btrfs(sb)
++              || au_test_ubifs(sb)
++              || au_test_hfsplus(sb)  /* maintained, but incorrect */
 +              /* || au_test_ext4(sb) */       /* untested */
 +              /* || au_test_ocfs2(sb) */      /* untested */
 +              /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
 +              /* || au_test_sysv(sb) */       /* untested */
-+              /* || au_test_ubifs(sb) */      /* untested */
 +              /* || au_test_minix(sb) */      /* untested */
 +              ;
 +}
@@ -8957,7 +9442,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/fstype.h linux-2.6.31/fs/aufs/fstype.h
 +#ifdef CONFIG_AUFS_BR_RAMFS
 +              || au_test_ramfs(sb)
 +#endif
-+              || au_test_ubifs(sb);
++              || au_test_ubifs(sb)
++              || au_test_btrfs(sb)
++              || au_test_hfsplus(sb);
 +}
 +
 +/*
@@ -9029,12 +9516,246 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/fstype.h linux-2.6.31/fs/aufs/fstype.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_FSTYPE_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.c
---- linux-2.6.31-vanilla/fs/aufs/hinotify.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/hinotify.c    2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,755 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/hfsnotify.c linux-2.6.33.1/fs/aufs/hfsnotify.c
+--- linux-2.6.33.1-vanilla/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/hfsnotify.c 2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,230 @@
++/*
++ * Copyright (C) 2005-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
++ */
++
++/*
++ * fsnotify for the lower directories
++ */
++
++#include "aufs.h"
++
++/* FS_IN_IGNORED is unnecessary */
++static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
++                               | FS_CREATE | FS_EVENT_ON_CHILD);
++static struct fsnotify_group *au_hfsn_group;
++
++static void au_hfsn_free_mark(struct fsnotify_mark_entry *entry)
++{
++#if 0
++      struct au_hnotify *hn = container_of(entry, struct au_hnotify,
++                                           hn_entry);
++      au_cache_free_hnotify(hn);
++#endif
++      AuDbg("here\n");
++}
++
++static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
++{
++      struct fsnotify_mark_entry *entry;
++
++      entry = &hn->hn_entry;
++      fsnotify_init_mark(entry, au_hfsn_free_mark);
++      entry->mask = AuHfsnMask;
++      return fsnotify_add_mark(entry, au_hfsn_group, h_inode);
++}
++
++static void au_hfsn_free(struct au_hnotify *hn)
++{
++      struct fsnotify_mark_entry *entry;
++
++      entry = &hn->hn_entry;
++      fsnotify_destroy_mark_by_entry(entry);
++      fsnotify_put_mark(entry);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
++{
++      struct fsnotify_mark_entry *entry;
++
++      entry = &hinode->hi_notify->hn_entry;
++      spin_lock(&entry->lock);
++      if (do_set) {
++              AuDebugOn(entry->mask & AuHfsnMask);
++              entry->mask |= AuHfsnMask;
++      } else {
++              AuDebugOn(!(entry->mask & AuHfsnMask));
++              entry->mask &= ~AuHfsnMask;
++      }
++      spin_unlock(&entry->lock);
++      /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* #define AuDbgHnotify */
++#ifdef AuDbgHnotify
++static char *au_hfsn_name(u32 mask)
++{
++#ifdef CONFIG_AUFS_DEBUG
++#define test_ret(flag)        if (mask & flag) \
++                              return #flag;
++      test_ret(FS_ACCESS);
++      test_ret(FS_MODIFY);
++      test_ret(FS_ATTRIB);
++      test_ret(FS_CLOSE_WRITE);
++      test_ret(FS_CLOSE_NOWRITE);
++      test_ret(FS_OPEN);
++      test_ret(FS_MOVED_FROM);
++      test_ret(FS_MOVED_TO);
++      test_ret(FS_CREATE);
++      test_ret(FS_DELETE);
++      test_ret(FS_DELETE_SELF);
++      test_ret(FS_MOVE_SELF);
++      test_ret(FS_UNMOUNT);
++      test_ret(FS_Q_OVERFLOW);
++      test_ret(FS_IN_IGNORED);
++      test_ret(FS_IN_ISDIR);
++      test_ret(FS_IN_ONESHOT);
++      test_ret(FS_EVENT_ON_CHILD);
++      return "";
++#undef test_ret
++#else
++      return "??";
++#endif
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static int au_hfsn_handle_event(struct fsnotify_group *group,
++                              struct fsnotify_event *event)
++{
++      int err;
++      struct au_hnotify *hnotify;
++      struct inode *h_dir, *h_inode;
++      __u32 mask;
++      struct fsnotify_mark_entry *entry;
++      struct qstr h_child_qstr = {
++              .name   = event->file_name,
++              .len    = event->name_len
++      };
++
++      AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
++
++      err = 0;
++      /* if IN_UNMOUNT happens, there must be another bug */
++      mask = event->mask;
++      AuDebugOn(mask & FS_UNMOUNT);
++      if (mask & (IN_IGNORED | IN_UNMOUNT))
++              goto out;
++
++      h_dir = event->to_tell;
++      h_inode = event->inode;
++#ifdef AuDbgHnotify
++      au_debug(1);
++      if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
++          || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
++              AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
++                    h_dir->i_ino, mask, au_hfsn_name(mask),
++                    AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
++              /* WARN_ON(1); */
++      }
++      au_debug(0);
++#endif
++
++      spin_lock(&h_dir->i_lock);
++      entry = fsnotify_find_mark_entry(group, h_dir);
++      spin_unlock(&h_dir->i_lock);
++      if (entry) {
++              hnotify = container_of(entry, struct au_hnotify, hn_entry);
++              err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
++              fsnotify_put_mark(entry);
++      }
++
++out:
++      return err;
++}
++
++/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
++/* it should be exported to modules */
++static bool au_hfsn_should_send_event(struct fsnotify_group *group,
++                                    struct inode *h_inode, __u32 mask)
++{
++      struct fsnotify_mark_entry *entry;
++      bool send;
++
++      spin_lock(&h_inode->i_lock);
++      entry = fsnotify_find_mark_entry(group, h_inode);
++      spin_unlock(&h_inode->i_lock);
++      if (!entry)
++              return false;
++
++      mask = (mask & ~FS_EVENT_ON_CHILD);
++      send = (entry->mask & mask);
++
++      /* find took a reference */
++      fsnotify_put_mark(entry);
++
++      return send;
++}
++
++static struct fsnotify_ops au_hfsn_ops = {
++      .should_send_event      = au_hfsn_should_send_event,
++      .handle_event           = au_hfsn_handle_event
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int __init au_hfsn_init(void)
++{
++      int err;
++      unsigned int gn;
++      const unsigned int gn_max = 10;
++
++      gn = 0;
++      for (gn = 0; gn < gn_max; gn++) {
++              au_hfsn_group = fsnotify_obtain_group(gn, AuHfsnMask,
++                                                    &au_hfsn_ops);
++              if (au_hfsn_group != ERR_PTR(-EEXIST))
++                      break;
++      }
++
++      err = 0;
++      if (IS_ERR(au_hfsn_group)) {
++              pr_err("fsnotify_obtain_group() failed %u times\n", gn_max);
++              err = PTR_ERR(au_hfsn_group);
++      }
++
++      AuTraceErr(err);
++      return err;
++}
++
++static void au_hfsn_fin(void)
++{
++      fsnotify_put_group(au_hfsn_group);
++}
++
++const struct au_hnotify_op au_hnotify_op = {
++      .ctl            = au_hfsn_ctl,
++      .alloc          = au_hfsn_alloc,
++      .free           = au_hfsn_free,
++
++      .fin            = au_hfsn_fin,
++      .init           = au_hfsn_init
++};
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/hfsplus.c linux-2.6.33.1/fs/aufs/hfsplus.c
+--- linux-2.6.33.1-vanilla/fs/aufs/hfsplus.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/hfsplus.c   2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,58 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * 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
@@ -9052,7 +9773,69 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 + */
 +
 +/*
-+ * inotify for the lower directories
++ * special support for filesystems which aqucires an inode mutex
++ * at final closing a file, eg, hfsplus.
++ *
++ * This trick is very simple and stupid, just to open the file before really
++ * neceeary open to tell hfsplus that this is not the final closing.
++ * The caller should call au_h_open_pre() after acquiring the inode mutex,
++ * and au_h_open_post() after releasing it.
++ */
++
++#include <linux/file.h>
++#include "aufs.h"
++
++struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      struct file *h_file;
++      struct dentry *h_dentry;
++
++      h_dentry = au_h_dptr(dentry, bindex);
++      AuDebugOn(!h_dentry);
++      AuDebugOn(!h_dentry->d_inode);
++      IMustLock(h_dentry->d_inode);
++
++      h_file = NULL;
++      if (au_test_hfsplus(h_dentry->d_sb)
++          && S_ISREG(h_dentry->d_inode->i_mode))
++              h_file = au_h_open(dentry, bindex,
++                                 O_RDONLY | O_NOATIME | O_LARGEFILE,
++                                 /*file*/NULL);
++      return h_file;
++}
++
++void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
++                  struct file *h_file)
++{
++      if (h_file) {
++              fput(h_file);
++              au_sbr_put(dentry->d_sb, bindex);
++      }
++}
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/hinotify.c linux-2.6.33.1/fs/aufs/hinotify.c
+--- linux-2.6.33.1-vanilla/fs/aufs/hinotify.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/hinotify.c  2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,227 @@
++/*
++ * Copyright (C) 2005-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
++ */
++
++/*
++ * inotify for the lower directories (deprecated)
 + */
 +
 +#include "aufs.h"
@@ -9060,70 +9843,58 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
 +static struct inotify_handle *au_hin_handle;
 +
-+AuCacheFuncs(hinotify, HINOTIFY);
++/* ---------------------------------------------------------------------- */
 +
-+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
-+               struct inode *h_inode)
++static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
 +{
 +      int err;
-+      struct au_hinotify *hin;
 +      s32 wd;
++      struct inotify_watch *watch;
 +
-+      err = -ENOMEM;
-+      hin = au_cache_alloc_hinotify();
-+      if (hin) {
-+              AuDebugOn(hinode->hi_notify);
-+              hinode->hi_notify = hin;
-+              hin->hin_aufs_inode = inode;
-+
-+              inotify_init_watch(&hin->hin_watch);
-+              wd = inotify_add_watch(au_hin_handle, &hin->hin_watch, h_inode,
-+                                     AuHinMask);
-+              if (wd >= 0)
-+                      return 0; /* success */
++      err = -EEXIST;
++      wd = inotify_find_watch(au_hin_handle, h_inode, &watch);
++      if (wd >= 0) {
++              put_inotify_watch(watch);
++              goto out;
++      }
 +
++      err = 0;
++      inotify_init_watch(&hn->hn_watch);
++      wd = inotify_add_watch(au_hin_handle, &hn->hn_watch, h_inode,
++                             AuHinMask);
++      if (unlikely(wd < 0)) {
 +              err = wd;
-+              put_inotify_watch(&hin->hin_watch);
-+              au_cache_free_hinotify(hin);
-+              hinode->hi_notify = NULL;
++              put_inotify_watch(&hn->hn_watch);
 +      }
 +
++out:
 +      return err;
 +}
 +
-+void au_hin_free(struct au_hinode *hinode)
++static void au_hin_free(struct au_hnotify *hn)
 +{
 +      int err;
-+      struct au_hinotify *hin;
 +
-+      hin = hinode->hi_notify;
-+      if (hin) {
-+              err = 0;
-+              if (atomic_read(&hin->hin_watch.count))
-+                      err = inotify_rm_watch(au_hin_handle, &hin->hin_watch);
-+              if (unlikely(err))
-+                      /* it means the watch is already removed */
-+                      AuWarn("failed inotify_rm_watch() %d\n", err);
-+              au_cache_free_hinotify(hin);
-+              hinode->hi_notify = NULL;
-+      }
++      err = 0;
++      if (atomic_read(&hn->hn_watch.count))
++              err = inotify_rm_watch(au_hin_handle, &hn->hn_watch);
++      if (unlikely(err))
++              /* it means the watch is already removed */
++              pr_warning("failed inotify_rm_watch() %d\n", err);
 +}
 +
 +/* ---------------------------------------------------------------------- */
 +
-+void au_hin_ctl(struct au_hinode *hinode, int do_set)
++static void au_hin_ctl(struct au_hinode *hinode, int do_set)
 +{
 +      struct inode *h_inode;
 +      struct inotify_watch *watch;
 +
-+      if (!hinode->hi_notify)
-+              return;
-+
 +      h_inode = hinode->hi_inode;
 +      IMustLock(h_inode);
 +
 +      /* todo: try inotify_find_update_watch()? */
-+      watch = &hinode->hi_notify->hin_watch;
++      watch = &hinode->hi_notify->hn_watch;
 +      mutex_lock(&h_inode->inotify_mutex);
 +      /* mutex_lock(&watch->ih->mutex); */
 +      if (do_set) {
@@ -9137,7 +9908,219 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      mutex_unlock(&h_inode->inotify_mutex);
 +}
 +
-+void au_reset_hinotify(struct inode *inode, unsigned int flags)
++/* ---------------------------------------------------------------------- */
++
++#ifdef AuDbgHnotify
++static char *in_name(u32 mask)
++{
++#ifdef CONFIG_AUFS_DEBUG
++#define test_ret(flag)        if (mask & flag) \
++                              return #flag;
++      test_ret(IN_ACCESS);
++      test_ret(IN_MODIFY);
++      test_ret(IN_ATTRIB);
++      test_ret(IN_CLOSE_WRITE);
++      test_ret(IN_CLOSE_NOWRITE);
++      test_ret(IN_OPEN);
++      test_ret(IN_MOVED_FROM);
++      test_ret(IN_MOVED_TO);
++      test_ret(IN_CREATE);
++      test_ret(IN_DELETE);
++      test_ret(IN_DELETE_SELF);
++      test_ret(IN_MOVE_SELF);
++      test_ret(IN_UNMOUNT);
++      test_ret(IN_Q_OVERFLOW);
++      test_ret(IN_IGNORED);
++      return "";
++#undef test_ret
++#else
++      return "??";
++#endif
++}
++#endif
++
++static u32 au_hin_conv_mask(u32 mask)
++{
++      u32 conv;
++
++      conv = 0;
++#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0
++      do_conv(ACCESS);
++      do_conv(MODIFY);
++      do_conv(ATTRIB);
++      do_conv(CLOSE_WRITE);
++      do_conv(CLOSE_NOWRITE);
++      do_conv(OPEN);
++      do_conv(MOVED_FROM);
++      do_conv(MOVED_TO);
++      do_conv(CREATE);
++      do_conv(DELETE);
++      do_conv(DELETE_SELF);
++      do_conv(MOVE_SELF);
++      do_conv(UNMOUNT);
++      do_conv(Q_OVERFLOW);
++#undef do_conv
++#define do_conv(flag) conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0
++      do_conv(IGNORED);
++      /* do_conv(ISDIR); */
++      /* do_conv(ONESHOT); */
++#undef do_conv
++
++      return conv;
++}
++
++static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
++                       u32 mask, u32 cookie __maybe_unused,
++                       const char *h_child_name, struct inode *h_child_inode)
++{
++      struct au_hnotify *hnotify;
++      struct qstr h_child_qstr = {
++              .name = h_child_name
++      };
++
++      /* if IN_UNMOUNT happens, there must be another bug */
++      AuDebugOn(mask & IN_UNMOUNT);
++      if (mask & (IN_IGNORED | IN_UNMOUNT)) {
++              put_inotify_watch(watch);
++              return;
++      }
++
++#ifdef AuDbgHnotify
++      au_debug(1);
++      if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
++              AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
++                    " hi%lu\n",
++                    watch->inode->i_ino, wd, mask, in_name(mask), cookie,
++                    h_child_name ? h_child_name : "",
++                    h_child_inode ? h_child_inode->i_ino : 0);
++              WARN_ON(1);
++      }
++      au_debug(0);
++#endif
++
++      if (h_child_name)
++              h_child_qstr.len = strlen(h_child_name);
++      hnotify = container_of(watch, struct au_hnotify, hn_watch);
++      mask = au_hin_conv_mask(mask);
++      au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
++}
++
++static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
++{
++      return;
++}
++
++static struct inotify_operations aufs_inotify_ops = {
++      .handle_event   = aufs_inotify,
++      .destroy_watch  = aufs_inotify_destroy
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int __init au_hin_init(void)
++{
++      int err;
++
++      err = 0;
++      au_hin_handle = inotify_init(&aufs_inotify_ops);
++      if (IS_ERR(au_hin_handle))
++              err = PTR_ERR(au_hin_handle);
++
++      AuTraceErr(err);
++      return err;
++}
++
++static void au_hin_fin(void)
++{
++      inotify_destroy(au_hin_handle);
++}
++
++const struct au_hnotify_op au_hnotify_op = {
++      .ctl            = au_hin_ctl,
++      .alloc          = au_hin_alloc,
++      .free           = au_hin_free,
++
++      .fin            = au_hin_fin,
++      .init           = au_hin_init
++};
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/hnotify.c linux-2.6.33.1/fs/aufs/hnotify.c
+--- linux-2.6.33.1-vanilla/fs/aufs/hnotify.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/hnotify.c   2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,671 @@
++/*
++ * Copyright (C) 2005-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
++ */
++
++/*
++ * abstraction to notify the direct changes on lower directories
++ */
++
++#include "aufs.h"
++
++int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
++              struct inode *h_inode)
++{
++      int err;
++      struct au_hnotify *hn;
++
++      err = -ENOMEM;
++      hn = au_cache_alloc_hnotify();
++      if (hn) {
++              hn->hn_aufs_inode = inode;
++              err = au_hnotify_op.alloc(hn, h_inode);
++              if (!err)
++                      hinode->hi_notify = hn;
++              else {
++                      au_cache_free_hnotify(hn);
++                      /*
++                       * The upper dir was removed by udba, but the same named
++                       * dir left. In this case, aufs assignes a new inode
++                       * number and set the monitor again.
++                       * For the lower dir, the old monitnor is still left.
++                       */
++                      if (err == -EEXIST)
++                              err = 0;
++              }
++      }
++
++      return err;
++}
++
++void au_hn_free(struct au_hinode *hinode)
++{
++      struct au_hnotify *hn;
++
++      hn = hinode->hi_notify;
++      if (hn) {
++              au_hnotify_op.free(hn);
++              au_cache_free_hnotify(hn);
++              hinode->hi_notify = NULL;
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_hn_ctl(struct au_hinode *hinode, int do_set)
++{
++      if (hinode->hi_notify)
++              au_hnotify_op.ctl(hinode, do_set);
++}
++
++void au_hn_reset(struct inode *inode, unsigned int flags)
 +{
 +      aufs_bindex_t bindex, bend;
 +      struct inode *hi;
@@ -9165,7 +10148,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +
 +/* ---------------------------------------------------------------------- */
 +
-+static int hin_xino(struct inode *inode, struct inode *h_inode)
++static int hn_xino(struct inode *inode, struct inode *h_inode)
 +{
 +      int err;
 +      aufs_bindex_t bindex, bend, bfound, bstart;
@@ -9173,7 +10156,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +
 +      err = 0;
 +      if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
-+              AuWarn("branch root dir was changed\n");
++              pr_warning("branch root dir was changed\n");
 +              goto out;
 +      }
 +
@@ -9186,12 +10169,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +              goto out;
 +      }
 +#endif
-+      for (bindex = bstart; bindex <= bend; bindex++) {
++      for (bindex = bstart; bindex <= bend; bindex++)
 +              if (au_h_iptr(inode, bindex) == h_inode) {
 +                      bfound = bindex;
 +                      break;
 +              }
-+      }
 +      if (bfound < 0)
 +              goto out;
 +
@@ -9212,7 +10194,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      return err;
 +}
 +
-+static int hin_gen_tree(struct dentry *dentry)
++static int hn_gen_tree(struct dentry *dentry)
 +{
 +      int err, i, j, ndentry;
 +      struct au_dcsub_pages dpages;
@@ -9259,8 +10241,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +/*
 + * return 0 if processed.
 + */
-+static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
-+                          const unsigned int isdir)
++static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
++                         const unsigned int isdir)
 +{
 +      int err;
 +      struct dentry *d;
@@ -9268,7 +10250,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +
 +      err = 1;
 +      if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
-+              AuWarn("branch root dir was changed\n");
++              pr_warning("branch root dir was changed\n");
 +              err = 0;
 +              goto out;
 +      }
@@ -9300,7 +10282,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +
 +              dname = &d->d_name;
 +              if (dname->len == nlen && !memcmp(dname->name, name, nlen))
-+                      err = hin_gen_tree(d);
++                      err = hn_gen_tree(d);
 +              dput(d);
 +      }
 +
@@ -9309,7 +10291,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      return err;
 +}
 +
-+static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
++static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
 +{
 +      int err;
 +      struct inode *inode;
@@ -9318,7 +10300,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      if (IS_ROOT(dentry)
 +          /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
 +              ) {
-+              AuWarn("branch root dir was changed\n");
++              pr_warning("branch root dir was changed\n");
 +              return 0;
 +      }
 +
@@ -9331,7 +10313,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      } else {
 +              au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
 +              if (inode)
-+                      err = hin_gen_tree(dentry);
++                      err = hn_gen_tree(dentry);
 +      }
 +
 +      AuTraceErr(err);
@@ -9340,18 +10322,32 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +
 +/* ---------------------------------------------------------------------- */
 +
-+/* hinotify job flags */
-+#define AuHinJob_XINO0                1
-+#define AuHinJob_GEN          (1 << 1)
-+#define AuHinJob_DIRENT               (1 << 2)
-+#define AuHinJob_ISDIR                (1 << 3)
-+#define AuHinJob_TRYXINO0     (1 << 4)
-+#define AuHinJob_MNTPNT               (1 << 5)
-+#define au_ftest_hinjob(flags, name)  ((flags) & AuHinJob_##name)
-+#define au_fset_hinjob(flags, name)   { (flags) |= AuHinJob_##name; }
-+#define au_fclr_hinjob(flags, name)   { (flags) &= ~AuHinJob_##name; }
-+
-+struct hin_job_args {
++/* hnotify job flags */
++#define AuHnJob_XINO0         1
++#define AuHnJob_GEN           (1 << 1)
++#define AuHnJob_DIRENT                (1 << 2)
++#define AuHnJob_ISDIR         (1 << 3)
++#define AuHnJob_TRYXINO0      (1 << 4)
++#define AuHnJob_MNTPNT                (1 << 5)
++#define au_ftest_hnjob(flags, name)   ((flags) & AuHnJob_##name)
++#define au_fset_hnjob(flags, name)    { (flags) |= AuHnJob_##name; }
++#define au_fclr_hnjob(flags, name)    { (flags) &= ~AuHnJob_##name; }
++
++enum {
++      AuHn_CHILD,
++      AuHn_PARENT,
++      AuHnLast
++};
++
++struct au_hnotify_args {
++      struct inode *h_dir, *dir, *h_child_inode;
++      u32 mask;
++      unsigned int flags[AuHnLast];
++      unsigned int h_child_nlen;
++      char h_child_name[];
++};
++
++struct hn_job_args {
 +      unsigned int flags;
 +      struct inode *inode, *h_inode, *dir, *h_dir;
 +      struct dentry *dentry;
@@ -9359,36 +10355,36 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      int h_nlen;
 +};
 +
-+static int hin_job(struct hin_job_args *a)
++static int hn_job(struct hn_job_args *a)
 +{
-+      const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
++      const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
 +
 +      /* reset xino */
-+      if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
-+              hin_xino(a->inode, a->h_inode); /* ignore this error */
++      if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
++              hn_xino(a->inode, a->h_inode); /* ignore this error */
 +
-+      if (au_ftest_hinjob(a->flags, TRYXINO0)
++      if (au_ftest_hnjob(a->flags, TRYXINO0)
 +          && a->inode
 +          && a->h_inode) {
 +              mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
 +              if (!a->h_inode->i_nlink)
-+                      hin_xino(a->inode, a->h_inode); /* ignore this error */
++                      hn_xino(a->inode, a->h_inode); /* ignore this error */
 +              mutex_unlock(&a->h_inode->i_mutex);
 +      }
 +
 +      /* make the generation obsolete */
-+      if (au_ftest_hinjob(a->flags, GEN)) {
++      if (au_ftest_hnjob(a->flags, GEN)) {
 +              int err = -1;
 +              if (a->inode)
-+                      err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
-+                                             isdir);
++                      err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
++                                            isdir);
 +              if (err && a->dentry)
-+                      hin_gen_by_name(a->dentry, isdir);
++                      hn_gen_by_name(a->dentry, isdir);
 +              /* ignore this error */
 +      }
 +
 +      /* make dir entries obsolete */
-+      if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
++      if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
 +              struct au_vdir *vdir;
 +
 +              vdir = au_ivdir(a->inode);
@@ -9399,44 +10395,17 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      }
 +
 +      /* can do nothing but warn */
-+      if (au_ftest_hinjob(a->flags, MNTPNT)
++      if (au_ftest_hnjob(a->flags, MNTPNT)
 +          && a->dentry
 +          && d_mountpoint(a->dentry))
-+              AuWarn("mount-point %.*s is removed or renamed\n",
-+                     AuDLNPair(a->dentry));
++              pr_warning("mount-point %.*s is removed or renamed\n",
++                         AuDLNPair(a->dentry));
 +
 +      return 0;
 +}
 +
 +/* ---------------------------------------------------------------------- */
 +
-+static char *in_name(u32 mask)
-+{
-+#ifdef CONFIG_AUFS_DEBUG
-+#define test_ret(flag)        if (mask & flag) \
-+                              return #flag;
-+      test_ret(IN_ACCESS);
-+      test_ret(IN_MODIFY);
-+      test_ret(IN_ATTRIB);
-+      test_ret(IN_CLOSE_WRITE);
-+      test_ret(IN_CLOSE_NOWRITE);
-+      test_ret(IN_OPEN);
-+      test_ret(IN_MOVED_FROM);
-+      test_ret(IN_MOVED_TO);
-+      test_ret(IN_CREATE);
-+      test_ret(IN_DELETE);
-+      test_ret(IN_DELETE_SELF);
-+      test_ret(IN_MOVE_SELF);
-+      test_ret(IN_UNMOUNT);
-+      test_ret(IN_Q_OVERFLOW);
-+      test_ret(IN_IGNORED);
-+      return "";
-+#undef test_ret
-+#else
-+      return "??";
-+#endif
-+}
-+
 +static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
 +                                         struct inode *dir)
 +{
@@ -9488,7 +10457,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +              goto out;
 +
 +      if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
-+              AuWarn("wrong root branch\n");
++              pr_warning("wrong root branch\n");
 +              iput(inode);
 +              inode = NULL;
 +              goto out;
@@ -9500,25 +10469,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      return inode;
 +}
 +
-+enum { CHILD, PARENT };
-+struct postproc_args {
-+      struct inode *h_dir, *dir, *h_child_inode;
-+      u32 mask;
-+      unsigned int flags[2];
-+      unsigned int h_child_nlen;
-+      char h_child_name[];
-+};
-+
-+static void postproc(void *_args)
++static void au_hn_bh(void *_args)
 +{
-+      struct postproc_args *a = _args;
++      struct au_hnotify_args *a = _args;
 +      struct super_block *sb;
 +      aufs_bindex_t bindex, bend, bfound;
 +      unsigned char xino, try_iput;
 +      int err;
 +      struct inode *inode;
 +      ino_t h_ino;
-+      struct hin_job_args args;
++      struct hn_job_args args;
 +      struct dentry *dentry;
 +      struct au_sbinfo *sbinfo;
 +
@@ -9526,8 +10486,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      AuDebugOn(!a->h_dir);
 +      AuDebugOn(!a->dir);
 +      AuDebugOn(!a->mask);
-+      AuDbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
-+            a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
++      AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
++            a->mask, a->dir->i_ino, a->h_dir->i_ino,
 +            a->h_child_inode ? a->h_child_inode->i_ino : 0);
 +
 +      inode = NULL;
@@ -9561,22 +10521,22 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +              h_ino = a->h_child_inode->i_ino;
 +
 +      if (a->h_child_nlen
-+          && (au_ftest_hinjob(a->flags[CHILD], GEN)
-+              || au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
++          && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
++              || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
 +              dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
 +                                            a->dir);
 +      try_iput = 0;
 +      if (dentry)
 +              inode = dentry->d_inode;
 +      if (xino && !inode && h_ino
-+          && (au_ftest_hinjob(a->flags[CHILD], XINO0)
-+              || au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
-+              || au_ftest_hinjob(a->flags[CHILD], GEN))) {
++          && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
++              || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
++              || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
 +              inode = lookup_wlock_by_ino(sb, bfound, h_ino);
 +              try_iput = 1;
 +          }
 +
-+      args.flags = a->flags[CHILD];
++      args.flags = a->flags[AuHn_CHILD];
 +      args.dentry = dentry;
 +      args.inode = inode;
 +      args.h_inode = a->h_child_inode;
@@ -9584,7 +10544,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      args.h_dir = a->h_dir;
 +      args.h_name = a->h_child_name;
 +      args.h_nlen = a->h_child_nlen;
-+      err = hin_job(&args);
++      err = hn_job(&args);
 +      if (dentry) {
 +              if (dentry->d_fsdata)
 +                      di_write_unlock(dentry);
@@ -9596,7 +10556,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      }
 +
 +      ii_write_lock_parent(a->dir);
-+      args.flags = a->flags[PARENT];
++      args.flags = a->flags[AuHn_PARENT];
 +      args.dentry = NULL;
 +      args.inode = a->dir;
 +      args.h_inode = a->h_dir;
@@ -9604,7 +10564,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      args.h_dir = NULL;
 +      args.h_name = NULL;
 +      args.h_nlen = 0;
-+      err = hin_job(&args);
++      err = hn_job(&args);
 +      ii_write_unlock(a->dir);
 +
 + out:
@@ -9619,49 +10579,29 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +
 +/* ---------------------------------------------------------------------- */
 +
-+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
-+                       u32 mask, u32 cookie __maybe_unused,
-+                       const char *h_child_name, struct inode *h_child_inode)
++int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
++             struct qstr *h_child_qstr, struct inode *h_child_inode)
 +{
-+      struct au_hinotify *hinotify;
-+      struct postproc_args *args;
-+      int len, wkq_err;
++      int err, len;
++      unsigned int flags[AuHnLast];
 +      unsigned char isdir, isroot, wh;
-+      char *p;
 +      struct inode *dir;
-+      unsigned int flags[2];
-+
-+      /* if IN_UNMOUNT happens, there must be another bug */
-+      AuDebugOn(mask & IN_UNMOUNT);
-+      if (mask & (IN_IGNORED | IN_UNMOUNT)) {
-+              put_inotify_watch(watch);
-+              return;
-+      }
-+#ifdef AuDbgHinotify
-+      au_debug(1);
-+      if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
-+              AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
-+                    " hi%lu\n",
-+                    watch->inode->i_ino, wd, mask, in_name(mask), cookie,
-+                    h_child_name ? h_child_name : "",
-+                    h_child_inode ? h_child_inode->i_ino : 0);
-+              WARN_ON(1);
-+      }
-+      au_debug(0);
-+#endif
++      struct au_hnotify_args *args;
++      char *p, *h_child_name;
 +
-+      hinotify = container_of(watch, struct au_hinotify, hin_watch);
-+      AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
-+      dir = igrab(hinotify->hin_aufs_inode);
++      err = 0;
++      AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
++      dir = igrab(hnotify->hn_aufs_inode);
 +      if (!dir)
-+              return;
++              goto out;
 +
 +      isroot = (dir->i_ino == AUFS_ROOT_INO);
-+      len = 0;
 +      wh = 0;
++      h_child_name = (void *)h_child_qstr->name;
++      len = h_child_qstr->len;
 +      if (h_child_name) {
-+              len = strlen(h_child_name);
-+              if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++              if (len > AUFS_WH_PFX_LEN
++                  && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
 +                      h_child_name += AUFS_WH_PFX_LEN;
 +                      len -= AUFS_WH_PFX_LEN;
 +                      wh = 1;
@@ -9671,37 +10611,31 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      isdir = 0;
 +      if (h_child_inode)
 +              isdir = !!S_ISDIR(h_child_inode->i_mode);
-+      flags[PARENT] = AuHinJob_ISDIR;
-+      flags[CHILD] = 0;
++      flags[AuHn_PARENT] = AuHnJob_ISDIR;
++      flags[AuHn_CHILD] = 0;
 +      if (isdir)
-+              flags[CHILD] = AuHinJob_ISDIR;
-+      switch (mask & IN_ALL_EVENTS) {
-+      case IN_MOVED_FROM:
-+      case IN_MOVED_TO:
-+              AuDebugOn(!h_child_name || !h_child_inode);
-+              au_fset_hinjob(flags[CHILD], GEN);
-+              au_fset_hinjob(flags[CHILD], XINO0);
-+              au_fset_hinjob(flags[CHILD], MNTPNT);
-+              au_fset_hinjob(flags[PARENT], DIRENT);
-+              break;
-+
-+      case IN_CREATE:
++              flags[AuHn_CHILD] = AuHnJob_ISDIR;
++      au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
++      au_fset_hnjob(flags[AuHn_CHILD], GEN);
++      switch (mask & FS_EVENTS_POSS_ON_CHILD) {
++      case FS_MOVED_FROM:
++      case FS_MOVED_TO:
++              au_fset_hnjob(flags[AuHn_CHILD], XINO0);
++              au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
++              /*FALLTHROUGH*/
++      case FS_CREATE:
 +              AuDebugOn(!h_child_name || !h_child_inode);
-+              au_fset_hinjob(flags[PARENT], DIRENT);
-+              au_fset_hinjob(flags[CHILD], GEN);
 +              break;
 +
-+      case IN_DELETE:
++      case FS_DELETE:
 +              /*
 +               * aufs never be able to get this child inode.
 +               * revalidation should be in d_revalidate()
 +               * by checking i_nlink, i_generation or d_unhashed().
 +               */
 +              AuDebugOn(!h_child_name);
-+              au_fset_hinjob(flags[PARENT], DIRENT);
-+              au_fset_hinjob(flags[CHILD], GEN);
-+              au_fset_hinjob(flags[CHILD], TRYXINO0);
-+              au_fset_hinjob(flags[CHILD], MNTPNT);
++              au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
++              au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
 +              break;
 +
 +      default:
@@ -9711,24 +10645,25 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      if (wh)
 +              h_child_inode = NULL;
 +
-+      /* iput() and kfree() will be called in postproc() */
++      err = -ENOMEM;
++      /* iput() and kfree() will be called in au_hnotify() */
 +      /*
 +       * inotify_mutex is already acquired and kmalloc/prune_icache may lock
 +       * iprune_mutex. strange.
 +       */
-+      lockdep_off();
++      /* lockdep_off(); */
 +      args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (unlikely(!args)) {
 +              AuErr1("no memory\n");
 +              iput(dir);
-+              return;
++              goto out;
 +      }
-+      args->flags[PARENT] = flags[PARENT];
-+      args->flags[CHILD] = flags[CHILD];
++      args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
++      args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
 +      args->mask = mask;
 +      args->dir = dir;
-+      args->h_dir = igrab(watch->inode);
++      args->h_dir = igrab(h_dir);
 +      if (h_child_inode)
 +              h_child_inode = igrab(h_child_inode); /* can be NULL */
 +      args->h_child_inode = h_child_inode;
@@ -9736,64 +10671,59 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/hinotify.c linux-2.6.31/fs/aufs/hinotify.
 +      if (len) {
 +              p = (void *)args;
 +              p += sizeof(*args);
-+              memcpy(p, h_child_name, len + 1);
++              memcpy(p, h_child_name, len);
++              p[len] = 0;
 +      }
 +
-+      lockdep_off();
-+      wkq_err = au_wkq_nowait(postproc, args, dir->i_sb);
-+      lockdep_on();
-+      if (unlikely(wkq_err))
-+              AuErr("wkq %d\n", wkq_err);
-+}
++      /* lockdep_off(); */
++      err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
++      /* lockdep_on(); */
++      if (unlikely(err)) {
++              pr_err("wkq %d\n", err);
++              iput(args->h_child_inode);
++              iput(args->h_dir);
++              iput(args->dir);
++              kfree(args);
++      }
 +
-+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
-+{
-+      return;
++out:
++      return err;
 +}
 +
-+static struct inotify_operations aufs_inotify_ops = {
-+      .handle_event   = aufs_inotify,
-+      .destroy_watch  = aufs_inotify_destroy
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static void au_hin_destroy_cache(void)
++static void au_hn_destroy_cache(void)
 +{
-+      kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
-+      au_cachep[AuCache_HINOTIFY] = NULL;
++      kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
++      au_cachep[AuCache_HNOTIFY] = NULL;
 +}
 +
-+int __init au_hinotify_init(void)
++int __init au_hnotify_init(void)
 +{
 +      int err;
 +
 +      err = -ENOMEM;
-+      au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
-+      if (au_cachep[AuCache_HINOTIFY]) {
-+              err = 0;
-+              au_hin_handle = inotify_init(&aufs_inotify_ops);
-+              if (IS_ERR(au_hin_handle)) {
-+                      err = PTR_ERR(au_hin_handle);
-+                      au_hin_destroy_cache();
-+              }
++      au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
++      if (au_cachep[AuCache_HNOTIFY]) {
++              err = au_hnotify_op.init();
++              if (unlikely(err))
++                      au_hn_destroy_cache();
 +      }
 +      AuTraceErr(err);
 +      return err;
 +}
 +
-+void au_hinotify_fin(void)
++void au_hnotify_fin(void)
 +{
-+      inotify_destroy(au_hin_handle);
-+      if (au_cachep[AuCache_HINOTIFY])
-+              au_hin_destroy_cache();
++      au_hnotify_op.fin();
++      /* cf. au_cache_fin() */
++      if (au_cachep[AuCache_HNOTIFY])
++              au_hn_destroy_cache();
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/iinfo.c linux-2.6.31/fs/aufs/iinfo.c
---- linux-2.6.31-vanilla/fs/aufs/iinfo.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/iinfo.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,283 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/iinfo.c linux-2.6.33.1/fs/aufs/iinfo.c
+--- linux-2.6.33.1-vanilla/fs/aufs/iinfo.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/iinfo.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,282 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -9843,7 +10773,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/iinfo.c linux-2.6.31/fs/aufs/iinfo.c
 +
 +void au_hiput(struct au_hinode *hinode)
 +{
-+      au_hin_free(hinode);
++      au_hn_free(hinode);
 +      dput(hinode->hi_whdentry);
 +      iput(hinode->hi_inode);
 +}
@@ -9856,8 +10786,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/iinfo.c linux-2.6.31/fs/aufs/iinfo.c
 +      flags = 0;
 +      if (au_opt_test(mnt_flags, XINO))
 +              au_fset_hi(flags, XINO);
-+      if (isdir && au_opt_test(mnt_flags, UDBA_HINOTIFY))
-+              au_fset_hi(flags, HINOTIFY);
++      if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
++              au_fset_hi(flags, HNOTIFY);
 +      return flags;
 +}
 +
@@ -9873,7 +10803,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/iinfo.c linux-2.6.31/fs/aufs/iinfo.c
 +      hinode = iinfo->ii_hinode + bindex;
 +      hi = hinode->hi_inode;
 +      AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
-+      AuDebugOn(h_inode && hi);
 +
 +      if (hi)
 +              au_hiput(hinode);
@@ -9894,11 +10823,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/iinfo.c linux-2.6.31/fs/aufs/iinfo.c
 +                              AuIOErr1("failed au_xino_write() %d\n", err);
 +              }
 +
-+              if (au_ftest_hi(flags, HINOTIFY)
-+                  && au_br_hinotifyable(br->br_perm)) {
-+                      err = au_hin_alloc(hinode, inode, h_inode);
++              if (au_ftest_hi(flags, HNOTIFY)
++                  && au_br_hnotifyable(br->br_perm)) {
++                      err = au_hn_alloc(hinode, inode, h_inode);
 +                      if (unlikely(err))
-+                              AuIOErr1("au_hin_alloc() %d\n", err);
++                              AuIOErr1("au_hn_alloc() %d\n", err);
 +              }
 +      }
 +}
@@ -10075,12 +11004,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/iinfo.c linux-2.6.31/fs/aufs/iinfo.c
 +      kfree(iinfo->ii_hinode);
 +      AuRwDestroy(&iinfo->ii_rwsem);
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
---- linux-2.6.31-vanilla/fs/aufs/inode.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/inode.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,413 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/inode.c linux-2.6.33.1/fs/aufs/inode.c
+--- linux-2.6.33.1-vanilla/fs/aufs/inode.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/inode.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,412 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -10125,7 +11054,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +      int err;
 +      aufs_bindex_t bindex, new_bindex;
 +      unsigned char update;
-+      struct inode *first;
 +      struct au_hinode *p, *q, tmp;
 +      struct super_block *sb;
 +      struct au_iinfo *iinfo;
@@ -10140,7 +11068,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +              goto out;
 +
 +      p = iinfo->ii_hinode + iinfo->ii_bstart;
-+      first = p->hi_inode;
 +      err = 0;
 +      for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
 +           bindex++, p++) {
@@ -10152,7 +11079,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +                      continue;
 +
 +              if (new_bindex < 0) {
-+                      update++;
++                      update = 1;
 +                      au_hiput(p);
 +                      p->hi_inode = NULL;
 +                      continue;
@@ -10182,11 +11109,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +
 +int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
 +{
-+      int err, update;
++      int err;
 +      unsigned int flags;
 +      aufs_bindex_t bindex, bend;
-+      unsigned char isdir;
-+      struct inode *first;
++      unsigned char isdir, update;
 +      struct au_hinode *p;
 +      struct au_iinfo *iinfo;
 +
@@ -10197,7 +11123,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +      update = 0;
 +      iinfo = au_ii(inode);
 +      p = iinfo->ii_hinode + iinfo->ii_bstart;
-+      first = p->hi_inode;
 +      isdir = S_ISDIR(inode->i_mode);
 +      flags = au_hi_flags(inode, isdir);
 +      bend = au_dbend(dentry);
@@ -10233,6 +11158,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +      au_refresh_hinode_attr(inode, update && isdir);
 +
 + out:
++      AuTraceErr(err);
 +      return err;
 +}
 +
@@ -10277,7 +11203,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +      case S_IFSOCK:
 +              btail = au_dbtail(dentry);
 +              inode->i_op = &aufs_iop;
-+              init_special_inode(inode, mode, h_inode->i_rdev);
++              au_init_special_fop(inode, mode, h_inode->i_rdev);
 +              break;
 +      default:
 +              AuIOErr("Unknown file type 0%o\n", mode);
@@ -10285,13 +11211,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +              goto out;
 +      }
 +
-+      /* do not set inotify for whiteouted dirs (SHWH mode) */
++      /* do not set hnotify for whiteouted dirs (SHWH mode) */
 +      flags = au_hi_flags(inode, isdir);
 +      if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
-+          && au_ftest_hi(flags, HINOTIFY)
++          && au_ftest_hi(flags, HNOTIFY)
 +          && dentry->d_name.len > AUFS_WH_PFX_LEN
 +          && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
-+              au_fclr_hi(flags, HINOTIFY);
++              au_fclr_hi(flags, HNOTIFY);
 +      iinfo = au_ii(inode);
 +      iinfo->ii_bstart = bstart;
 +      iinfo->ii_bend = btail;
@@ -10417,13 +11343,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +      if (inode->i_state & I_NEW) {
 +              ii_write_lock_new_child(inode);
 +              err = set_inode(inode, dentry);
-+              unlock_new_inode(inode);
-+              if (!err)
++              if (!err) {
++                      unlock_new_inode(inode);
 +                      goto out; /* success */
++              }
 +
-+              iget_failed(inode);
 +              ii_write_unlock(inode);
-+              goto out_iput;
++              iget_failed(inode);
++              goto out_err;
 +      } else if (!must_new) {
 +              err = reval_inode(inode, dentry, &match);
 +              if (!err)
@@ -10446,6 +11373,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +
 + out_iput:
 +      iput(inode);
++ out_err:
 +      inode = ERR_PTR(err);
 + out:
 +      return inode;
@@ -10492,12 +11420,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.c linux-2.6.31/fs/aufs/inode.c
 +              mask |= MAY_READ; /* force permission check */
 +      return au_test_h_perm(h_inode, mask);
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.h linux-2.6.31/fs/aufs/inode.h
---- linux-2.6.31-vanilla/fs/aufs/inode.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/inode.h       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,497 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/inode.h linux-2.6.33.1/fs/aufs/inode.h
+--- linux-2.6.33.1-vanilla/fs/aufs/inode.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/inode.h     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,492 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -10524,24 +11452,28 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.h linux-2.6.31/fs/aufs/inode.h
 +#ifdef __KERNEL__
 +
 +#include <linux/fs.h>
-+#include <linux/inotify.h>
++#include <linux/fsnotify.h>
 +#include <linux/aufs_type.h>
 +#include "rwsem.h"
 +
 +struct vfsmount;
 +
-+struct au_hinotify {
-+#ifdef CONFIG_AUFS_HINOTIFY
-+      struct inotify_watch    hin_watch;
-+      struct inode            *hin_aufs_inode;        /* no get/put */
++struct au_hnotify {
++#ifdef CONFIG_AUFS_HNOTIFY
++#ifdef CONFIG_AUFS_HFSNOTIFY
++      struct fsnotify_mark_entry      hn_entry;
++#else
++      struct inotify_watch            hn_watch;
++#endif
++      struct inode                    *hn_aufs_inode; /* no get/put */
 +#endif
 +};
 +
 +struct au_hinode {
 +      struct inode            *hi_inode;
 +      aufs_bindex_t           hi_id;
-+#ifdef CONFIG_AUFS_HINOTIFY
-+      struct au_hinotify      *hi_notify;
++#ifdef CONFIG_AUFS_HNOTIFY
++      struct au_hnotify       *hi_notify;
 +#endif
 +
 +      /* reference to the copied-up whiteout with get/put */
@@ -10680,14 +11612,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.h linux-2.6.31/fs/aufs/inode.h
 +
 +/* hinode flags */
 +#define AuHi_XINO     1
-+#define AuHi_HINOTIFY (1 << 1)
++#define AuHi_HNOTIFY  (1 << 1)
 +#define au_ftest_hi(flags, name)      ((flags) & AuHi_##name)
 +#define au_fset_hi(flags, name)               { (flags) |= AuHi_##name; }
 +#define au_fclr_hi(flags, name)               { (flags) &= ~AuHi_##name; }
 +
-+#ifndef CONFIG_AUFS_HINOTIFY
-+#undef AuHi_HINOTIFY
-+#define AuHi_HINOTIFY 0
++#ifndef CONFIG_AUFS_HNOTIFY
++#undef AuHi_HNOTIFY
++#define AuHi_HNOTIFY  0
 +#endif
 +
 +void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
@@ -10701,14 +11633,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.h linux-2.6.31/fs/aufs/inode.h
 +int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
 +
 +/* plink.c */
-+void au_plink_block_maintain(struct super_block *sb);
++void au_plink_maint_block(struct super_block *sb);
++void au_plink_maint_leave(struct file *file);
 +#ifdef CONFIG_AUFS_DEBUG
 +void au_plink_list(struct super_block *sb);
 +#else
-+static inline void au_plink_list(struct super_block *sb)
-+{
-+      /* nothing */
-+}
++AuStubVoid(au_plink_list, struct super_block *sb)
 +#endif
 +int au_plink_test(struct inode *inode);
 +struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
@@ -10723,7 +11653,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.h linux-2.6.31/fs/aufs/inode.h
 +/* lock subclass for iinfo */
 +enum {
 +      AuLsc_II_CHILD,         /* child first */
-+      AuLsc_II_CHILD2,        /* rename(2), link(2), and cpup at hinotify */
++      AuLsc_II_CHILD2,        /* rename(2), link(2), and cpup at hnotify */
 +      AuLsc_II_CHILD3,        /* copyup dirs */
 +      AuLsc_II_PARENT,        /* see AuLsc_I_PARENT in vfsub.h */
 +      AuLsc_II_PARENT2,
@@ -10796,6 +11726,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.h linux-2.6.31/fs/aufs/inode.h
 +               && iinfo->ii_higen == h_inode->i_generation);
 +}
 +
++static inline void au_iigen_dec(struct inode *inode)
++{
++#ifdef CONFIG_AUFS_HNOTIFY
++      atomic_dec_return(&au_ii(inode)->ii_generation);
++#endif
++}
++
 +/* ---------------------------------------------------------------------- */
 +
 +static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
@@ -10899,106 +11836,92 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/inode.h linux-2.6.31/fs/aufs/inode.h
 +
 +/* ---------------------------------------------------------------------- */
 +
-+#ifdef CONFIG_AUFS_HINOTIFY
-+/* hinotify.c */
-+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
-+               struct inode *h_inode);
-+void au_hin_free(struct au_hinode *hinode);
-+void au_hin_ctl(struct au_hinode *hinode, int do_set);
-+void au_reset_hinotify(struct inode *inode, unsigned int flags);
++#ifdef CONFIG_AUFS_HNOTIFY
++struct au_hnotify_op {
++      void (*ctl)(struct au_hinode *hinode, int do_set);
++      int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
++      void (*free)(struct au_hnotify *hn);
 +
-+int __init au_hinotify_init(void);
-+void au_hinotify_fin(void);
++      void (*fin)(void);
++      int (*init)(void);
++};
 +
-+static inline
-+void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
-+{
-+      hinode->hi_notify = val;
-+}
++/* hnotify.c */
++int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
++              struct inode *h_inode);
++void au_hn_free(struct au_hinode *hinode);
++void au_hn_ctl(struct au_hinode *hinode, int do_set);
++void au_hn_reset(struct inode *inode, unsigned int flags);
++int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
++             struct qstr *h_child_qstr, struct inode *h_child_inode);
++int __init au_hnotify_init(void);
++void au_hnotify_fin(void);
 +
-+static inline void au_iigen_dec(struct inode *inode)
++/* hinotify.c */
++extern const struct au_hnotify_op au_hnotify_op;
++
++static inline
++void au_hn_init(struct au_hinode *hinode)
 +{
-+      atomic_dec_return(&au_ii(inode)->ii_generation);
++      hinode->hi_notify = NULL;
 +}
 +
 +#else
 +static inline
-+int au_hin_alloc(struct au_hinode *hinode __maybe_unused,
-+               struct inode *inode __maybe_unused,
-+               struct inode *h_inode __maybe_unused)
++int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
++              struct inode *inode __maybe_unused,
++              struct inode *h_inode __maybe_unused)
 +{
 +      return -EOPNOTSUPP;
 +}
 +
-+static inline void au_hin_free(struct au_hinode *hinode __maybe_unused)
-+{
-+      /* nothing */
-+}
-+
-+static inline void au_hin_ctl(struct au_hinode *hinode __maybe_unused,
-+                            int do_set __maybe_unused)
-+{
-+      /* nothing */
-+}
-+
-+static inline void au_reset_hinotify(struct inode *inode __maybe_unused,
-+                                   unsigned int flags __maybe_unused)
-+{
-+      /* nothing */
-+}
-+
-+static inline int au_hinotify_init(void)
-+{
-+      return 0;
-+}
-+
-+#define au_hinotify_fin()     do {} while (0)
-+
-+static inline
-+void au_hin_init(struct au_hinode *hinode __maybe_unused,
-+               struct au_hinotify *val __maybe_unused)
-+{
-+      /* empty */
-+}
-+#endif /* CONFIG_AUFS_HINOTIFY */
++AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
++AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
++         int do_set __maybe_unused)
++AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
++         unsigned int flags __maybe_unused)
++AuStubInt0(__init au_hnotify_init, void)
++AuStubVoid(au_hnotify_fin, void)
++AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
++#endif /* CONFIG_AUFS_HNOTIFY */
 +
-+static inline void au_hin_suspend(struct au_hinode *hdir)
++static inline void au_hn_suspend(struct au_hinode *hdir)
 +{
-+      au_hin_ctl(hdir, /*do_set*/0);
++      au_hn_ctl(hdir, /*do_set*/0);
 +}
 +
-+static inline void au_hin_resume(struct au_hinode *hdir)
++static inline void au_hn_resume(struct au_hinode *hdir)
 +{
-+      au_hin_ctl(hdir, /*do_set*/1);
++      au_hn_ctl(hdir, /*do_set*/1);
 +}
 +
-+static inline void au_hin_imtx_lock(struct au_hinode *hdir)
++static inline void au_hn_imtx_lock(struct au_hinode *hdir)
 +{
 +      mutex_lock(&hdir->hi_inode->i_mutex);
-+      au_hin_suspend(hdir);
++      au_hn_suspend(hdir);
 +}
 +
-+static inline void au_hin_imtx_lock_nested(struct au_hinode *hdir,
-+                                         unsigned int sc __maybe_unused)
++static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
++                                        unsigned int sc __maybe_unused)
 +{
 +      mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
-+      au_hin_suspend(hdir);
++      au_hn_suspend(hdir);
 +}
 +
-+static inline void au_hin_imtx_unlock(struct au_hinode *hdir)
++static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
 +{
-+      au_hin_resume(hdir);
++      au_hn_resume(hdir);
 +      mutex_unlock(&hdir->hi_inode->i_mutex);
 +}
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_INODE_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/ioctl.c linux-2.6.31/fs/aufs/ioctl.c
---- linux-2.6.31-vanilla/fs/aufs/ioctl.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/ioctl.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,47 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/ioctl.c linux-2.6.33.1/fs/aufs/ioctl.c
+--- linux-2.6.33.1-vanilla/fs/aufs/ioctl.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/ioctl.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,129 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -11018,10 +11941,67 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/ioctl.c linux-2.6.31/fs/aufs/ioctl.c
 +/*
 + * ioctl
 + * plink-management and readdir in userspace.
++ * assist the pathconf(3) wrapper library.
 + */
 +
++#include <linux/file.h>
 +#include "aufs.h"
 +
++static int au_wbr_fd(struct path *path)
++{
++      int err, fd, flags;
++      aufs_bindex_t wbi, bindex, bend;
++      struct file *h_file;
++      struct super_block *sb;
++      struct dentry *root;
++      struct au_branch *wbr;
++
++      err = get_unused_fd();
++      if (unlikely(err < 0))
++              goto out;
++      fd = err;
++
++      flags = O_RDONLY | O_DIRECTORY;
++      if (force_o_largefile())
++              flags |= O_LARGEFILE;
++
++      wbi = 0;
++      sb = path->dentry->d_sb;
++      root = sb->s_root;
++      aufs_read_lock(root, AuLock_IR);
++      wbr = au_sbr(sb, wbi);
++      if (!(path->mnt->mnt_flags & MNT_READONLY)
++          && !au_br_writable(wbr->br_perm)) {
++              bend = au_sbend(sb);
++              for (bindex = 1; bindex <= bend; bindex++) {
++                      wbr = au_sbr(sb, bindex);
++                      if (au_br_writable(wbr->br_perm)) {
++                              wbi = bindex;
++                              break;
++                      }
++              }
++              wbr = au_sbr(sb, wbi);
++      }
++      AuDbg("wbi %d\n", wbi);
++      h_file = au_h_open(root, wbi, flags, NULL);
++      aufs_read_unlock(root, AuLock_IR);
++      err = PTR_ERR(h_file);
++      if (IS_ERR(h_file))
++              goto out_fd;
++
++      atomic_dec(&wbr->br_count); /* cf. au_h_open() */
++      fd_install(fd, h_file);
++      err = fd;
++      goto out; /* success */
++
++ out_fd:
++      put_unused_fd(fd);
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
 +long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
 +{
 +      long err;
@@ -11037,19 +12017,44 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/ioctl.c linux-2.6.31/fs/aufs/ioctl.c
 +              err = au_rdu_ioctl(file, cmd, arg);
 +              break;
 +
++      case AUFS_CTL_WBR_FD:
++              err = au_wbr_fd(&file->f_path);
++              break;
++
 +      default:
-+              err = -EINVAL;
++              /* do not call the lower */
++              AuDbg("0x%x\n", cmd);
++              err = -ENOTTY;
++      }
++
++      AuTraceErr(err);
++      return err;
++}
++
++long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
++{
++      long err;
++
++      switch (cmd) {
++      case AUFS_CTL_WBR_FD:
++              err = au_wbr_fd(&file->f_path);
++              break;
++
++      default:
++              /* do not call the lower */
++              AuDbg("0x%x\n", cmd);
++              err = -ENOTTY;
 +      }
 +
 +      AuTraceErr(err);
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.c
---- linux-2.6.31-vanilla/fs/aufs/i_op_add.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/i_op_add.c    2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,649 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op_add.c linux-2.6.33.1/fs/aufs/i_op_add.c
+--- linux-2.6.33.1-vanilla/fs/aufs/i_op_add.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/i_op_add.c  2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,672 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -11143,6 +12148,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +      struct dentry *h_dentry;
 +      struct inode *h_inode;
 +
++      err = -ENAMETOOLONG;
++      if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
++              goto out;
++
 +      h_dentry = au_h_dptr(dentry, bindex);
 +      h_inode = h_dentry->d_inode;
 +      if (!dentry->d_inode) {
@@ -11166,13 +12175,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +              }
 +      }
 +
-+      err = -EIO;
++      err = 0;
 +      /* expected parent dir is locked */
 +      if (unlikely(h_parent != h_dentry->d_parent))
-+              goto out;
-+      err = 0;
++              err = -EIO;
 +
 + out:
++      AuTraceErr(err);
 +      return err;
 +}
 +
@@ -11193,6 +12202,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +      unsigned int udba;
 +      aufs_bindex_t bcpup;
 +
++      AuDbg("%.*s\n", AuDLNPair(dentry));
++
 +      err = au_wr_dir(dentry, src_dentry, wr_dir_args);
 +      bcpup = err;
 +      wh_dentry = ERR_PTR(err);
@@ -11209,13 +12220,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +
 +      h_parent = au_pinned_h_parent(pin);
 +      if (udba != AuOpt_UDBA_NONE
-+          && au_dbstart(dentry) == bcpup) {
++          && au_dbstart(dentry) == bcpup)
 +              err = au_may_add(dentry, bcpup, h_parent,
 +                               au_ftest_wrdir(wr_dir_args->flags, ISDIR));
-+              wh_dentry = ERR_PTR(err);
-+              if (unlikely(err))
-+                      goto out_unpin;
-+      }
++      else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
++              err = -ENAMETOOLONG;
++      wh_dentry = ERR_PTR(err);
++      if (unlikely(err))
++              goto out_unpin;
 +
 +      br = au_sbr(sb, bcpup);
 +      if (dt) {
@@ -11275,6 +12287,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +              .flags          = AuWrDir_ADD_ENTRY
 +      };
 +
++      AuDbg("%.*s\n", AuDLNPair(dentry));
 +      IMustLock(dir);
 +
 +      parent = dentry->d_parent; /* dir inode is locked */
@@ -11382,6 +12395,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +      int err;
 +      struct dentry *h_src_dentry;
 +      struct mutex *h_mtx;
++      struct file *h_file;
 +
 +      di_read_lock_parent(a->src_parent, AuLock_IR);
 +      err = au_test_and_cpup_dirs(src_dentry, a->bdst);
@@ -11396,9 +12410,15 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +      if (unlikely(err))
 +              goto out;
 +      mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
-+      err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
-+                               AuCpup_DTIME /* | AuCpup_KEEPLINO */);
++      h_file = au_h_open_pre(src_dentry, a->bsrc);
++      if (IS_ERR(h_file)) {
++              err = PTR_ERR(h_file);
++              h_file = NULL;
++      } else
++              err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
++                                       AuCpup_DTIME /* | AuCpup_KEEPLINO */);
 +      mutex_unlock(h_mtx);
++      au_h_open_post(src_dentry, a->bsrc, h_file);
 +      au_unpin(&a->pin);
 +
 + out:
@@ -11413,6 +12433,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +      struct inode *h_inode, *inode;
 +      struct dentry *h_src_dentry;
 +      struct super_block *sb;
++      struct file *h_file;
 +
 +      plink = 0;
 +      h_inode = NULL;
@@ -11426,9 +12447,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 +              au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
 +              h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
 +              mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+              err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
-+                                       AuCpup_KEEPLINO, a->parent);
++              h_file = au_h_open_pre(src_dentry, a->bsrc);
++              if (IS_ERR(h_file)) {
++                      err = PTR_ERR(h_file);
++                      h_file = NULL;
++              } else
++                      err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
++                                               -1, AuCpup_KEEPLINO,
++                                               a->parent);
 +              mutex_unlock(&h_inode->i_mutex);
++              au_h_open_post(src_dentry, a->bsrc, h_file);
 +              au_set_h_dptr(src_dentry, a->bdst, NULL);
 +              au_set_dbstart(src_dentry, a->bsrc);
 +      } else {
@@ -11697,12 +12725,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_add.c linux-2.6.31/fs/aufs/i_op_add.
 + out:
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
---- linux-2.6.31-vanilla/fs/aufs/i_op.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/i_op.c        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,891 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op.c linux-2.6.33.1/fs/aufs/i_op.c
+--- linux-2.6.33.1-vanilla/fs/aufs/i_op.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/i_op.c      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,909 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -11755,7 +12783,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +              && write_mask && !(mask & MAY_READ))
 +          || !h_inode->i_op->permission) {
 +              /* AuLabel(generic_permission); */
-+              err = generic_permission(h_inode, mask, NULL);
++              err = generic_permission(h_inode, mask,
++                                       h_inode->i_op->check_acl);
 +      } else {
 +              /* AuLabel(h_inode->permission); */
 +              err = h_inode->i_op->permission(h_inode, mask);
@@ -11764,10 +12793,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +
 +      if (!err)
 +              err = devcgroup_inode_permission(h_inode, mask);
-+      if (!err)
-+              err = security_inode_permission
-+                      (h_inode, mask & (MAY_READ | MAY_WRITE | MAY_EXEC
-+                                        | MAY_APPEND));
++      if (!err) {
++              mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
++              err = security_inode_permission(h_inode, mask);
++      }
 +
 +#if 0
 +      if (!err) {
@@ -11790,8 +12819,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +{
 +      int err;
 +      aufs_bindex_t bindex, bend;
-+      const unsigned char isdir = !!S_ISDIR(inode->i_mode);
-+      const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++      const unsigned char isdir = !!S_ISDIR(inode->i_mode),
++              write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
 +      struct inode *h_inode;
 +      struct super_block *sb;
 +      struct au_branch *br;
@@ -11812,7 +12841,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +              bindex = au_ibstart(inode);
 +              br = au_sbr(sb, bindex);
 +              err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
-+              if (write_mask && !err) {
++              if (write_mask
++                  && !err
++                  && !special_file(h_inode->i_mode)) {
 +                      /* test whether the upper writable branch exists */
 +                      err = -EROFS;
 +                      for (; bindex >= 0; bindex--)
@@ -11862,6 +12893,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +
 +      sb = dir->i_sb;
 +      si_read_lock(sb, AuLock_FLUSH);
++      ret = ERR_PTR(-ENAMETOOLONG);
++      if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
++              goto out;
 +      err = au_alloc_dinfo(dentry);
 +      ret = ERR_PTR(err);
 +      if (unlikely(err))
@@ -12034,7 +13068,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      if (!p->hdir)
 +              return;
 +
-+      au_hin_imtx_unlock(p->hdir);
++      au_hn_imtx_unlock(p->hdir);
 +      if (!au_ftest_pin(p->flags, DI_LOCKED))
 +              di_read_unlock(p->parent, AuLock_IR);
 +      iput(p->hdir->hi_inode);
@@ -12091,7 +13125,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      }
 +
 +      au_igrab(h_dir);
-+      au_hin_imtx_lock_nested(p->hdir, p->lsc_hi);
++      au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
 +
 +      if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
 +              err = -EBUSY;
@@ -12118,7 +13152,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 + out_unpin:
 +      au_unpin(p);
 + out_err:
-+      AuErr("err %d\n", err);
++      pr_err("err %d\n", err);
 +      err = au_busy_or_stale();
 + out:
 +      return err;
@@ -12173,6 +13207,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      aufs_bindex_t bstart;
 +      struct dentry *hi_wh, *parent;
 +      struct inode *inode;
++      struct file *h_file;
 +      struct au_wr_dir_args wr_dir_args = {
 +              .force_btgt     = -1,
 +              .flags          = 0
@@ -12206,13 +13241,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      if (d_unhashed(dentry) || (ia->ia_valid & ATTR_FILE))
 +              udba = AuOpt_UDBA_NONE;
 +      err = au_pin(&a->pin, dentry, a->btgt, udba, a->pin_flags);
-+      if (unlikely(err)) {
-+              if (parent) {
-+                      di_write_unlock(parent);
-+                      dput(parent);
-+              }
-+              goto out_dentry;
-+      }
++      if (unlikely(err))
++              goto out_parent;
++
 +      a->h_path.dentry = au_h_dptr(dentry, bstart);
 +      a->h_inode = a->h_path.dentry->d_inode;
 +      mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
@@ -12220,6 +13251,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
 +              sz = ia->ia_size;
 +
++      h_file = NULL;
 +      hi_wh = NULL;
 +      if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
 +              hi_wh = au_hi_wh(inode, a->btgt);
@@ -12236,12 +13268,19 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +              au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
 +              di_downgrade_lock(parent, AuLock_IR);
 +              dput(parent);
++              parent = NULL;
 +      }
 +      if (!au_ftest_icpup(a->flags, DID_CPUP))
 +              goto out; /* success */
 +
 +      if (!d_unhashed(dentry)) {
-+              err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
++              h_file = au_h_open_pre(dentry, bstart);
++              if (IS_ERR(h_file)) {
++                      err = PTR_ERR(h_file);
++                      h_file = NULL;
++              } else
++                      err = au_sio_cpup_simple(dentry, a->btgt, sz,
++                                               AuCpup_DTIME);
 +              if (!err)
 +                      a->h_path.dentry = au_h_dptr(dentry, a->btgt);
 +      } else if (!hi_wh)
@@ -12251,6 +13290,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +
 + 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;
 +      if (!err) {
 +              mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
@@ -12258,7 +13298,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      }
 +
 +      au_unpin(&a->pin);
-+
++ out_parent:
++      if (parent) {
++              di_write_unlock(parent);
++              dput(parent);
++      }
 + out_dentry:
 +      di_write_unlock(dentry);
 + out:
@@ -12303,6 +13347,19 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      }
 +
 +      a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
++      if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
++          == (ATTR_MODE | ATTR_CTIME)) {
++              err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
++                                        ia->ia_mode);
++              if (unlikely(err))
++                      goto out_unlock;
++      } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
++                 && (ia->ia_valid & ATTR_CTIME)) {
++              err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
++              if (unlikely(err))
++                      goto out_unlock;
++      }
++
 +      if (ia->ia_valid & ATTR_SIZE) {
 +              struct file *f;
 +
@@ -12354,17 +13411,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +              di_read_lock_parent(parent, AuLock_IR);
 +              /* returns a number of positive dentries */
 +              err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
-+              if (err > 0)
++              if (err >= 0)
 +                      err = au_refresh_hinode(inode, dentry);
 +              di_read_unlock(parent, AuLock_IR);
 +              dput(parent);
-+              if (unlikely(!err))
-+                      err = -EIO;
 +      }
 +      di_downgrade_lock(dentry, AuLock_IR);
 +      if (unlikely(err))
 +              di_read_unlock(dentry, AuLock_IR);
 +
++      AuTraceErr(err);
 +      return err;
 +}
 +
@@ -12415,14 +13471,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +              if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
 +                      di_read_lock_child(dentry, AuLock_IR);
 +              else {
-+                      /* NFSD may skip the revalidation */
-+                      if (!au_test_nfsd(current))
-+                              AuDebugOn(!IS_ROOT(dentry));
-+                      else {
-+                              err = au_busy_or_stale();
-+                              if (unlikely(!IS_ROOT(dentry)))
-+                                      goto out;
-+                      }
++                      AuDebugOn(IS_ROOT(dentry));
 +                      err = au_getattr_lock_reval(dentry, sigen);
 +                      if (unlikely(err))
 +                              goto out;
@@ -12479,10 +13528,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +
 +      err = -EINVAL;
 +      h_dentry = au_h_dptr(dentry, bindex);
-+      if (unlikely(/* !h_dentry
-+                   || !h_dentry->d_inode
-+                   || !h_dentry->d_inode->i_op
-+                   || */ !h_dentry->d_inode->i_op->readlink))
++      if (unlikely(!h_dentry->d_inode->i_op->readlink))
 +              goto out;
 +
 +      err = security_inode_readlink(h_dentry);
@@ -12518,7 +13564,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      mm_segment_t old_fs;
 +
 +      err = -ENOMEM;
-+      buf = __getname();
++      buf = __getname_gfp(GFP_NOFS);
 +      if (unlikely(!buf))
 +              goto out;
 +
@@ -12592,12 +13638,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op.c linux-2.6.31/fs/aufs/i_op.c
 +      .getattr        = aufs_getattr,
 +      .truncate_range = aufs_truncate_range
 +};
-diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_del.c linux-2.6.31/fs/aufs/i_op_del.c
---- linux-2.6.31-vanilla/fs/aufs/i_op_del.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/i_op_del.c    2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,468 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op_del.c linux-2.6.33.1/fs/aufs/i_op_del.c
+--- linux-2.6.33.1-vanilla/fs/aufs/i_op_del.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/i_op_del.c  2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,472 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -12793,9 +13839,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_del.c linux-2.6.31/fs/aufs/i_op_del.
 +              goto out; /* success, no need to create whiteout */
 +
 +      wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
-+      if (!IS_ERR(wh_dentry))
-+              goto out; /* success */
++      if (IS_ERR(wh_dentry))
++              goto out_unpin;
++
 +      /* returns with the parent is locked and wh_dentry is dget-ed */
++      goto out; /* success */
 +
 + out_unpin:
 +      au_unpin(pin);
@@ -12827,7 +13875,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_del.c linux-2.6.31/fs/aufs/i_op_del.
 +              goto out;
 +
 +      /* stop monitoring */
-+      au_hin_free(au_hi(dentry->d_inode, bindex));
++      au_hn_free(au_hi(dentry->d_inode, bindex));
 +
 +      if (!au_test_fs_remote(h_dentry->d_sb)) {
 +              dirwh = au_sbi(sb)->si_dirwh;
@@ -12847,6 +13895,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_del.c linux-2.6.31/fs/aufs/i_op_del.
 +      }
 +
 + out:
++      AuTraceErr(err);
 +      return err;
 +}
 +
@@ -13021,7 +14070,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_del.c linux-2.6.31/fs/aufs/i_op_del.
 +              }
 +      } else {
 +              /* stop monitoring */
-+              au_hin_free(au_hi(inode, bstart));
++              au_hn_free(au_hi(inode, bstart));
 +
 +              /* dir inode is locked */
 +              IMustLock(wh_dentry->d_parent->d_inode);
@@ -13062,14 +14111,15 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_del.c linux-2.6.31/fs/aufs/i_op_del.
 + out_unlock:
 +      aufs_read_unlock(dentry, AuLock_DW);
 + out:
++      AuTraceErr(err);
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.c
---- linux-2.6.31-vanilla/fs/aufs/i_op_ren.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/i_op_ren.c    2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,957 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op_ren.c linux-2.6.33.1/fs/aufs/i_op_ren.c
+--- linux-2.6.33.1-vanilla/fs/aufs/i_op_ren.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/i_op_ren.c  2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,977 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -13165,9 +14215,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 + * harmless.
 + */
 +
-+#define RevertFailure(fmt, args...) do { \
++#define RevertFailure(fmt, ...) do { \
 +      AuIOErr("revert failure: " fmt " (%d, %d)\n", \
-+              ##args, err, rerr); \
++              ##__VA_ARGS__, err, rerr); \
 +      err = -EIO; \
 +} while (0)
 +
@@ -13175,14 +14225,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +{
 +      int rerr;
 +
-+      au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++      au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
 +      rerr = au_diropq_remove(a->src_dentry, a->btgt);
-+      au_hin_imtx_unlock(a->src_hinode);
++      au_hn_imtx_unlock(a->src_hinode);
 +      if (rerr)
 +              RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
 +}
 +
-+
 +static void au_ren_rev_rename(int err, struct au_ren_args *a)
 +{
 +      int rerr;
@@ -13217,7 +14266,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +              RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
 +}
 +
-+
 +static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
 +{
 +      int rerr;
@@ -13238,10 +14286,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +      rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
 +      d_drop(a->h_path.dentry);
 +      dput(a->h_path.dentry);
-+      if (!rerr) {
-+              au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
++      if (!rerr)
 +              au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
-+      else
++      else
 +              RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
 +}
 +
@@ -13301,18 +14348,29 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +                                 a->dst_h_dir, &a->h_path);
 +      } else {
 +              struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++              struct file *h_file;
 +
 +              au_fset_ren(a->flags, CPUP);
 +              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
 +              au_set_dbstart(d, a->btgt);
 +              au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
-+              err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
-+                                       !AuCpup_DTIME, a->dst_parent);
-+              if (unlikely(err)) {
++              h_file = au_h_open_pre(d, a->src_bstart);
++              if (IS_ERR(h_file)) {
++                      err = PTR_ERR(h_file);
++                      h_file = NULL;
++              } else
++                      err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
++                                               !AuCpup_DTIME, a->dst_parent);
++              mutex_unlock(h_mtx);
++              au_h_open_post(d, a->src_bstart, h_file);
++              if (!err) {
++                      d = a->dst_dentry;
++                      au_set_h_dptr(d, a->btgt, NULL);
++                      au_update_dbstart(d);
++              } else {
 +                      au_set_h_dptr(d, a->btgt, NULL);
 +                      au_set_dbstart(d, a->src_bstart);
 +              }
-+              mutex_unlock(h_mtx);
 +      }
 +
 +      return err;
@@ -13331,8 +14389,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +          || au_test_fs_remote(a->h_dst->d_sb)) {
 +              err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
 +              if (unlikely(err))
-+                      AuWarn("failed removing whtmp dir %.*s (%d), "
-+                             "ignored.\n", AuDLNPair(a->h_dst), err);
++                      pr_warning("failed removing whtmp dir %.*s (%d), "
++                                 "ignored.\n", AuDLNPair(a->h_dst), err);
 +      } else {
 +              au_nhash_wh_free(&a->thargs->whlist);
 +              a->thargs->whlist = a->whlist;
@@ -13353,9 +14411,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +
 +      err = 0;
 +      a->src_hinode = au_hi(a->src_inode, a->btgt);
-+      au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++      au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
 +      diropq = au_diropq_create(a->src_dentry, a->btgt);
-+      au_hin_imtx_unlock(a->src_hinode);
++      au_hn_imtx_unlock(a->src_hinode);
 +      if (IS_ERR(diropq))
 +              err = PTR_ERR(diropq);
 +      dput(diropq);
@@ -13417,11 +14475,19 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +      /* cpup src */
 +      if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
 +              struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++              struct file *h_file;
 +
 +              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
-+              err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
-+                                       !AuCpup_DTIME);
++              AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
++              h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
++              if (IS_ERR(h_file)) {
++                      err = PTR_ERR(h_file);
++                      h_file = NULL;
++              } else
++                      err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
++                                               !AuCpup_DTIME);
 +              mutex_unlock(h_mtx);
++              au_h_open_post(a->src_dentry, a->src_bstart, h_file);
 +              if (unlikely(err))
 +                      goto out_whtmp;
 +      }
@@ -13645,6 +14711,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 + out:
 +      if (unlikely(err == -ENOENT || err == -EEXIST))
 +              err = -EIO;
++      AuTraceErr(err);
 +      return err;
 +}
 +
@@ -13893,6 +14960,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +      /* reduce stack space */
 +      struct au_ren_args *a;
 +
++      AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
 +      IMustLock(_src_dir);
 +      IMustLock(_dst_dir);
 +
@@ -13977,11 +15045,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +      if (unlikely(err))
 +              goto out_children;
 +
-+      if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) {
++      if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
 +              err = au_may_ren(a);
-+              if (unlikely(err))
-+                      goto out_hdir;
-+      }
++      else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
++              err = -ENAMETOOLONG;
++      if (unlikely(err))
++              goto out_hdir;
 +
 +      /* store timestamps to be revertible */
 +      au_ren_dt(a);
@@ -14023,12 +15092,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/i_op_ren.c linux-2.6.31/fs/aufs/i_op_ren.
 +              au_whtmp_rmdir_free(a->thargs);
 +      kfree(a);
 + out:
++      AuTraceErr(err);
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/Kconfig linux-2.6.31/fs/aufs/Kconfig
---- linux-2.6.31-vanilla/fs/aufs/Kconfig       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/Kconfig       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,140 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/Kconfig linux-2.6.33.1/fs/aufs/Kconfig
+--- linux-2.6.33.1-vanilla/fs/aufs/Kconfig     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/Kconfig     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,172 @@
 +config AUFS_FS
 +      tristate "Aufs (Advanced multi layered unification filesystem) support"
 +      depends on EXPERIMENTAL
@@ -14075,16 +15145,28 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/Kconfig linux-2.6.31/fs/aufs/Kconfig
 +      resources and has a minor impact to performance.
 +endchoice
 +
-+config AUFS_HINOTIFY
-+      bool "Use inotify to detect actions on a branch"
-+      depends on INOTIFY
++config AUFS_HNOTIFY
++      bool "Detect direct branch access (bypassing aufs)"
 +      help
 +      If you want to modify files on branches directly, eg. bypassing aufs,
 +      and want aufs to detect the changes of them fully, then enable this
-+      option and use 'udba=inotify' mount option.
++      option and use 'udba=notify' mount option.
 +      It will have a negative impact to the performance.
 +      See detail in aufs.5.
 +
++if AUFS_HNOTIFY
++choice
++      prompt ""
++      default AUFS_HFSNOTIFY
++config AUFS_HFSNOTIFY
++      bool "fsnotify"
++      select FSNOTIFY
++config AUFS_HINOTIFY
++      bool "inotify (DEPRECATED)"
++      depends on INOTIFY
++endchoice
++endif
++
 +config AUFS_EXPORT
 +      bool "NFS-exportable aufs"
 +      depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
@@ -14093,6 +15175,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/Kconfig linux-2.6.31/fs/aufs/Kconfig
 +      option. There are several requirements for this configuration.
 +      See detail in aufs.5.
 +
++config AUFS_INO_T_64
++      bool
++      depends on AUFS_EXPORT
++      depends on 64BIT && !(ALPHA || S390)
++      default y
++      help
++      Automatic configuration for internal use.
++      /* typedef unsigned long/int __kernel_ino_t */
++      /* alpha and s390x are int */
++
 +config AUFS_RDU
 +      bool "Readdir in userspace"
 +      help
@@ -14101,6 +15193,17 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/Kconfig linux-2.6.31/fs/aufs/Kconfig
 +      environment variables for your readdir(3).
 +      See detail in aufs.5.
 +
++config AUFS_SP_IATTR
++      bool "Respect the attributes (mtime/ctime mainly) of special files"
++      help
++      When you write something to a special file, some attributes of it
++      (mtime/ctime mainly) may be updated. Generally such updates are
++      less important (actually some device drivers and NFS ignore
++      it). But some applications (such like test program) requires
++      such updates. If you need these updates, then enable this
++      configuration which introduces some overhead.
++      Currently this configuration handles FIFO only.
++
 +config AUFS_SHWH
 +      bool "Show whiteouts"
 +      help
@@ -14132,19 +15235,19 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/Kconfig linux-2.6.31/fs/aufs/Kconfig
 +      It implements the internal poll(2) operation which is
 +      implemented by fuse only (curretnly).
 +
-+config AUFS_DEBUG
-+      bool "Debug aufs"
++config AUFS_POLL
++      bool
 +      help
-+      Enable this to compile aufs internal debug code.
-+      It will have a negative impact to the performance.
++      Automatic configuration for internal use.
 +
-+config AUFS_MAGIC_SYSRQ
-+      bool
-+      depends on AUFS_DEBUG && MAGIC_SYSRQ
++config AUFS_BR_HFSPLUS
++      bool "Hfsplus as an aufs branch"
++      depends on HFSPLUS_FS
 +      default y
 +      help
-+      Automatic configuration for internal use.
-+      When aufs supports Magic SysRq, enabled automatically.
++      If you want to use hfsplus fs as an aufs branch fs, then enable
++      this option. This option introduces a small overhead at
++      copying-up a file on hfsplus.
 +
 +config AUFS_BDEV_LOOP
 +      bool
@@ -14154,27 +15257,26 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/Kconfig linux-2.6.31/fs/aufs/Kconfig
 +      Automatic configuration for internal use.
 +      Convert =[ym] into =y.
 +
-+config AUFS_INO_T_64
-+      bool
-+      depends on AUFS_EXPORT
-+      depends on 64BIT && !(ALPHA || S390)
-+      default y
++config AUFS_DEBUG
++      bool "Debug aufs"
 +      help
-+      Automatic configuration for internal use.
-+      /* typedef unsigned long/int __kernel_ino_t */
-+      /* alpha and s390x are int */
++      Enable this to compile aufs internal debug code.
++      It will have a negative impact to the performance.
 +
-+config AUFS_POLL
++config AUFS_MAGIC_SYSRQ
 +      bool
++      depends on AUFS_DEBUG && MAGIC_SYSRQ
++      default y
 +      help
 +      Automatic configuration for internal use.
++      When aufs supports Magic SysRq, enabled automatically.
 +endif
-diff -Nur linux-2.6.31-vanilla/fs/aufs/loop.c linux-2.6.31/fs/aufs/loop.c
---- linux-2.6.31-vanilla/fs/aufs/loop.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/loop.c        2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/loop.c linux-2.6.33.1/fs/aufs/loop.c
+--- linux-2.6.33.1-vanilla/fs/aufs/loop.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/loop.c      2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,55 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -14228,12 +15330,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/loop.c linux-2.6.31/fs/aufs/loop.c
 +             && '0' <= c && c <= '9'
 +             && strncmp(current->comm, "loop", 4) == 0;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/loop.h linux-2.6.31/fs/aufs/loop.h
---- linux-2.6.31-vanilla/fs/aufs/loop.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/loop.h        2009-09-16 13:55:29.000000000 +0200
-@@ -0,0 +1,51 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/loop.h linux-2.6.33.1/fs/aufs/loop.h
+--- linux-2.6.33.1-vanilla/fs/aufs/loop.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/loop.h      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,43 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -14268,25 +15370,17 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/loop.h linux-2.6.31/fs/aufs/loop.h
 +                           struct dentry *h_d2);
 +int au_test_loopback_kthread(void);
 +#else
-+static inline
-+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
-+                           struct dentry *h_d2)
-+{
-+      return 0;
-+}
-+
-+static inline int au_test_loopback_kthread(void)
-+{
-+      return 0;
-+}
++AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
++         struct dentry *h_d1, struct dentry *h_d2)
++AuStubInt0(au_test_loopback_kthread, void)
 +#endif /* BLK_DEV_LOOP */
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_LOOP_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/magic.mk linux-2.6.31/fs/aufs/magic.mk
---- linux-2.6.31-vanilla/fs/aufs/magic.mk      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/magic.mk      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,52 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/magic.mk linux-2.6.33.1/fs/aufs/magic.mk
+--- linux-2.6.33.1-vanilla/fs/aufs/magic.mk    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/magic.mk    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,54 @@
 +
 +# defined in ${srctree}/fs/fuse/inode.c
 +# tristate
@@ -14306,10 +15400,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/magic.mk linux-2.6.31/fs/aufs/magic.mk
 +ccflags-y += -DDLMFS_MAGIC=0x76a9f425
 +endif
 +
-+# defined in ${srctree}/fs/ramfs/inode.c
-+# always true
-+ccflags-y += -DRAMFS_MAGIC=0x858458f6
-+
 +# defined in ${srctree}/fs/cifs/cifsfs.c
 +# tristate
 +ifdef CONFIG_CIFS_FS
@@ -14339,14 +15429,29 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/magic.mk linux-2.6.31/fs/aufs/magic.mk
 +ifdef CONFIG_UBIFS_FS
 +ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
 +endif
-diff -Nur linux-2.6.31-vanilla/fs/aufs/Makefile linux-2.6.31/fs/aufs/Makefile
---- linux-2.6.31-vanilla/fs/aufs/Makefile      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/Makefile      2009-09-16 13:55:29.000000000 +0200
-@@ -0,0 +1,24 @@
++
++# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
++# tristate
++ifdef CONFIG_HFSPLUS_FS
++ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
++endif
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/Makefile linux-2.6.33.1/fs/aufs/Makefile
+--- linux-2.6.33.1-vanilla/fs/aufs/Makefile    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/Makefile    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,37 @@
 +
 +include ${src}/magic.mk
++ifeq (${CONFIG_AUFS_FS},m)
++include ${src}/conf.mk
++endif
 +-include ${src}/priv_def.mk
 +
++# cf. include/linux/kernel.h
++# enable pr_debug
++ccflags-y += -DDEBUG
++ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
++      __func__, __LINE__, current->comm, current->pid'
++
 +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 \
@@ -14361,18 +15466,22 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/Makefile linux-2.6.31/fs/aufs/Makefile
 +aufs-$(CONFIG_SYSFS) += sysfs.o
 +aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
 +aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
++aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
++aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
 +aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
 +aufs-$(CONFIG_AUFS_EXPORT) += export.o
 +aufs-$(CONFIG_AUFS_POLL) += poll.o
 +aufs-$(CONFIG_AUFS_RDU) += rdu.o
++aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
++aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
 +aufs-$(CONFIG_AUFS_DEBUG) += debug.o
 +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
-diff -Nur linux-2.6.31-vanilla/fs/aufs/module.c linux-2.6.31/fs/aufs/module.c
---- linux-2.6.31-vanilla/fs/aufs/module.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/module.c      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,173 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/module.c linux-2.6.33.1/fs/aufs/module.c
+--- linux-2.6.33.1-vanilla/fs/aufs/module.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/module.c    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,166 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -14434,6 +15543,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.c linux-2.6.31/fs/aufs/module.c
 +static void au_cache_fin(void)
 +{
 +      int i;
++
++      /* including AuCache_HNOTIFY */
 +      for (i = 0; i < AuCache_Last; i++)
 +              if (au_cachep[i]) {
 +                      kmem_cache_destroy(au_cachep[i]);
@@ -14455,11 +15566,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.c linux-2.6.31/fs/aufs/module.c
 +      " -- Advanced multi layered unification filesystem");
 +MODULE_VERSION(AUFS_VERSION);
 +
-+/* it should be 'byte', but param_set_byte() prints it by "%c" */
-+short aufs_nwkq = AUFS_NWKQ_DEF;
-+MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
-+module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
-+
 +/* this module parameter has no meaning when SYSFS is disabled */
 +int sysaufs_brs = 1;
 +MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
@@ -14492,18 +15598,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.c linux-2.6.31/fs/aufs/module.c
 +
 +      sysaufs_brs_init();
 +      au_debug_init();
-+
-+      err = -EINVAL;
-+      if (unlikely(aufs_nwkq <= 0))
-+              goto out;
-+
 +      err = sysaufs_init();
 +      if (unlikely(err))
 +              goto out;
 +      err = au_wkq_init();
 +      if (unlikely(err))
 +              goto out_sysaufs;
-+      err = au_hinotify_init();
++      err = au_hnotify_init();
 +      if (unlikely(err))
 +              goto out_wkq;
 +      err = au_sysrq_init();
@@ -14515,7 +15616,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.c linux-2.6.31/fs/aufs/module.c
 +      err = register_filesystem(&aufs_fs_type);
 +      if (unlikely(err))
 +              goto out_cache;
-+      pr_info(AUFS_NAME " " AUFS_VERSION "\n");
++      /* since we define pr_fmt, call printk directly */
++      printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
 +      goto out; /* success */
 +
 + out_cache:
@@ -14523,7 +15625,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.c linux-2.6.31/fs/aufs/module.c
 + out_sysrq:
 +      au_sysrq_fin();
 + out_hin:
-+      au_hinotify_fin();
++      au_hnotify_fin();
 + out_wkq:
 +      au_wkq_fin();
 + out_sysaufs:
@@ -14537,19 +15639,19 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.c linux-2.6.31/fs/aufs/module.c
 +      unregister_filesystem(&aufs_fs_type);
 +      au_cache_fin();
 +      au_sysrq_fin();
-+      au_hinotify_fin();
++      au_hnotify_fin();
 +      au_wkq_fin();
 +      sysaufs_fin();
 +}
 +
 +module_init(aufs_init);
 +module_exit(aufs_exit);
-diff -Nur linux-2.6.31-vanilla/fs/aufs/module.h linux-2.6.31/fs/aufs/module.h
---- linux-2.6.31-vanilla/fs/aufs/module.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/module.h      2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/module.h linux-2.6.33.1/fs/aufs/module.h
+--- linux-2.6.33.1-vanilla/fs/aufs/module.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/module.h    2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,78 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -14581,7 +15683,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.h linux-2.6.31/fs/aufs/module.h
 +struct seq_file;
 +
 +/* module parameters */
-+extern short aufs_nwkq;
 +extern int sysaufs_brs;
 +
 +/* ---------------------------------------------------------------------- */
@@ -14600,38 +15701,39 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/module.h linux-2.6.31/fs/aufs/module.h
 +      AuCache_FINFO,
 +      AuCache_VDIR,
 +      AuCache_DEHSTR,
-+#ifdef CONFIG_AUFS_HINOTIFY
-+      AuCache_HINOTIFY,
++#ifdef CONFIG_AUFS_HNOTIFY
++      AuCache_HNOTIFY,
 +#endif
 +      AuCache_Last
 +};
 +
-+#define AuCache(type) KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT)
++#define AuCache(type) KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
 +
 +extern struct kmem_cache *au_cachep[];
 +
 +#define AuCacheFuncs(name, index) \
-+static inline void *au_cache_alloc_##name(void) \
++static inline struct au_##name *au_cache_alloc_##name(void) \
 +{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
-+static inline void au_cache_free_##name(void *p) \
++static inline void au_cache_free_##name(struct au_##name *p) \
 +{ kmem_cache_free(au_cachep[AuCache_##index], p); }
 +
 +AuCacheFuncs(dinfo, DINFO);
 +AuCacheFuncs(icntnr, ICNTNR);
 +AuCacheFuncs(finfo, FINFO);
 +AuCacheFuncs(vdir, VDIR);
-+AuCacheFuncs(dehstr, DEHSTR);
-+
-+/*  ---------------------------------------------------------------------- */
++AuCacheFuncs(vdir_dehstr, DEHSTR);
++#ifdef CONFIG_AUFS_HNOTIFY
++AuCacheFuncs(hnotify, HNOTIFY);
++#endif
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_MODULE_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
---- linux-2.6.31-vanilla/fs/aufs/opts.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/opts.c        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,1546 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/opts.c linux-2.6.33.1/fs/aufs/opts.c
+--- linux-2.6.33.1-vanilla/fs/aufs/opts.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/opts.c      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,1565 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -14815,7 +15917,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      {AuBrPerm_RO, NULL}
 +};
 +
-+static int br_perm_val(char *perm)
++static int noinline_for_stack br_perm_val(char *perm)
 +{
 +      int val;
 +      substring_t args[MAX_OPT_ARGS];
@@ -14834,17 +15936,34 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +static match_table_t udbalevel = {
 +      {AuOpt_UDBA_REVAL, "reval"},
 +      {AuOpt_UDBA_NONE, "none"},
-+#ifdef CONFIG_AUFS_HINOTIFY
-+      {AuOpt_UDBA_HINOTIFY, "inotify"},
++#ifdef CONFIG_AUFS_HNOTIFY
++      {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
++#ifdef CONFIG_AUFS_HFSNOTIFY
++      {AuOpt_UDBA_HNOTIFY, "fsnotify"},
++#else
++      {AuOpt_UDBA_HNOTIFY, "inotify"},
++#endif
 +#endif
 +      {-1, NULL}
 +};
 +
-+static int udba_val(char *str)
++static void au_warn_inotify(int val, char *str)
++{
++#ifdef CONFIG_AUFS_HINOTIFY
++      if (val == AuOpt_UDBA_HNOTIFY
++          && !strcmp(str, "inotify"))
++              AuWarn1("udba=inotify is deprecated, use udba=notify\n");
++#endif
++}
++
++static int noinline_for_stack udba_val(char *str)
 +{
++      int val;
 +      substring_t args[MAX_OPT_ARGS];
 +
-+      return match_token(str, udbalevel, args);
++      val = match_token(str, udbalevel, args);
++      au_warn_inotify(val, str);
++      return val;
 +}
 +
 +const char *au_optstr_udba(int udba)
@@ -14877,7 +15996,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 + * gave up calling memparse() since it uses simple_strtoull() instead of
 + * strict_...().
 + */
-+static int au_match_ull(substring_t *s, unsigned long long *result)
++static int noinline_for_stack
++au_match_ull(substring_t *s, unsigned long long *result)
 +{
 +      int err;
 +      unsigned int len;
@@ -14903,7 +16023,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      if (!au_match_ull(arg, &ull))
 +              create->mfsrr_watermark = ull;
 +      else {
-+              AuErr("bad integer in %s\n", str);
++              pr_err("bad integer in %s\n", str);
 +              err = -EINVAL;
 +      }
 +
@@ -14919,14 +16039,15 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      if (!match_int(arg, &n) && 0 <= n)
 +              create->mfs_second = n;
 +      else {
-+              AuErr("bad integer in %s\n", str);
++              pr_err("bad integer in %s\n", str);
 +              err = -EINVAL;
 +      }
 +
 +      return err;
 +}
 +
-+static int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
++static int noinline_for_stack
++au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
 +{
 +      int err, e;
 +      substring_t args[MAX_OPT_ARGS];
@@ -14978,7 +16099,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      {-1, NULL}
 +};
 +
-+static int au_wbr_copyup_val(char *str)
++static int noinline_for_stack au_wbr_copyup_val(char *str)
 +{
 +      substring_t args[MAX_OPT_ARGS];
 +
@@ -15227,7 +16348,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +              opt->type = Opt_add;
 +              goto out;
 +      }
-+      AuErr("lookup failed %s (%d)\n", add->pathname, err);
++      pr_err("lookup failed %s (%d)\n", add->pathname, err);
 +      err = -EINVAL;
 +
 + out:
@@ -15243,7 +16364,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +
 +      err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
 +      if (unlikely(err))
-+              AuErr("lookup failed %s (%d)\n", del->pathname, err);
++              pr_err("lookup failed %s (%d)\n", del->pathname, err);
 +
 +      return err;
 +}
@@ -15259,7 +16380,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      root = sb->s_root;
 +      aufs_read_lock(root, AuLock_FLUSH);
 +      if (bindex < 0 || au_sbend(sb) < bindex) {
-+              AuErr("out of bounds, %d\n", bindex);
++              pr_err("out of bounds, %d\n", bindex);
 +              goto out;
 +      }
 +
@@ -15273,7 +16394,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +}
 +#endif
 +
-+static int au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
++static int noinline_for_stack
++au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
 +{
 +      int err;
 +      struct path path;
@@ -15283,14 +16405,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      mod->path = args[0].from;
 +      p = strchr(mod->path, '=');
 +      if (unlikely(!p)) {
-+              AuErr("no permssion %s\n", args[0].from);
++              pr_err("no permssion %s\n", args[0].from);
 +              goto out;
 +      }
 +
 +      *p++ = 0;
 +      err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
 +      if (unlikely(err)) {
-+              AuErr("lookup failed %s (%d)\n", mod->path, err);
++              pr_err("lookup failed %s (%d)\n", mod->path, err);
 +              goto out;
 +      }
 +
@@ -15314,7 +16436,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      root = sb->s_root;
 +      aufs_read_lock(root, AuLock_FLUSH);
 +      if (bindex < 0 || au_sbend(sb) < bindex) {
-+              AuErr("out of bounds, %d\n", bindex);
++              pr_err("out of bounds, %d\n", bindex);
 +              goto out;
 +      }
 +
@@ -15344,7 +16466,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      err = -EINVAL;
 +      if (unlikely(file->f_dentry->d_sb == sb)) {
 +              fput(file);
-+              AuErr("%s must be outside\n", args[0].from);
++              pr_err("%s must be outside\n", args[0].from);
 +              goto out;
 +      }
 +
@@ -15356,10 +16478,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      return err;
 +}
 +
-+static
-+int au_opts_parse_xino_itrunc_path(struct super_block *sb,
-+                                 struct au_opt_xino_itrunc *xino_itrunc,
-+                                 substring_t args[])
++static int noinline_for_stack
++au_opts_parse_xino_itrunc_path(struct super_block *sb,
++                             struct au_opt_xino_itrunc *xino_itrunc,
++                             substring_t args[])
 +{
 +      int err;
 +      aufs_bindex_t bend, bindex;
@@ -15368,7 +16490,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +
 +      err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
 +      if (unlikely(err)) {
-+              AuErr("lookup failed %s (%d)\n", args[0].from, err);
++              pr_err("lookup failed %s (%d)\n", args[0].from, err);
 +              goto out;
 +      }
 +
@@ -15386,7 +16508,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      path_put(&path);
 +
 +      if (unlikely(xino_itrunc->bindex < 0)) {
-+              AuErr("no such branch %s\n", args[0].from);
++              pr_err("no such branch %s\n", args[0].from);
 +              err = -EINVAL;
 +      }
 +
@@ -15444,7 +16566,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +                      break;
 +              case Opt_add:
 +                      if (unlikely(match_int(&a->args[0], &n))) {
-+                              AuErr("bad integer in %s\n", opt_str);
++                              pr_err("bad integer in %s\n", opt_str);
 +                              break;
 +                      }
 +                      bindex = n;
@@ -15474,7 +16596,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +              case Opt_idel:
 +                      del->pathname = "(indexed)";
 +                      if (unlikely(match_int(&args[0], &n))) {
-+                              AuErr("bad integer in %s\n", opt_str);
++                              pr_err("bad integer in %s\n", opt_str);
 +                              break;
 +                      }
 +                      err = au_opts_parse_idel(sb, n, &opt->del, a->args);
@@ -15491,7 +16613,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +              case Opt_imod:
 +                      u.mod->path = "(indexed)";
 +                      if (unlikely(match_int(&a->args[0], &n))) {
-+                              AuErr("bad integer in %s\n", opt_str);
++                              pr_err("bad integer in %s\n", opt_str);
 +                              break;
 +                      }
 +                      err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
@@ -15515,13 +16637,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +              case Opt_itrunc_xino:
 +                      u.xino_itrunc = &opt->xino_itrunc;
 +                      if (unlikely(match_int(&a->args[0], &n))) {
-+                              AuErr("bad integer in %s\n", opt_str);
++                              pr_err("bad integer in %s\n", opt_str);
 +                              break;
 +                      }
 +                      u.xino_itrunc->bindex = n;
 +                      aufs_read_lock(root, AuLock_FLUSH);
 +                      if (n < 0 || au_sbend(sb) < n) {
-+                              AuErr("out of bounds, %d\n", n);
++                              pr_err("out of bounds, %d\n", n);
 +                              aufs_read_unlock(root, !AuLock_IR);
 +                              break;
 +                      }
@@ -15547,12 +16669,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +                      if (unlikely(match_int(&a->args[0], &n)
 +                                   || n < 0
 +                                   || n > KMALLOC_MAX_SIZE)) {
-+                              AuErr("bad integer in %s\n", opt_str);
++                              pr_err("bad integer in %s\n", opt_str);
 +                              break;
 +                      }
 +                      if (unlikely(n && n < NAME_MAX)) {
-+                              AuErr("rdblk must be larger than %d\n",
-+                                    NAME_MAX);
++                              pr_err("rdblk must be larger than %d\n",
++                                     NAME_MAX);
 +                              break;
 +                      }
 +                      opt->rdblk = n;
@@ -15564,7 +16686,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +                                   || n < 0
 +                                   || n * sizeof(struct hlist_head)
 +                                   > KMALLOC_MAX_SIZE)) {
-+                              AuErr("bad integer in %s\n", opt_str);
++                              pr_err("bad integer in %s\n", opt_str);
 +                              break;
 +                      }
 +                      opt->rdhash = n;
@@ -15605,7 +16727,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +                              err = 0;
 +                              opt->type = token;
 +                      } else
-+                              AuErr("wrong value, %s\n", opt_str);
++                              pr_err("wrong value, %s\n", opt_str);
 +                      break;
 +
 +              case Opt_wbr_create:
@@ -15616,7 +16738,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +                              err = 0;
 +                              opt->type = token;
 +                      } else
-+                              AuErr("wrong value, %s\n", opt_str);
++                              pr_err("wrong value, %s\n", opt_str);
 +                      break;
 +              case Opt_wbr_copyup:
 +                      opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
@@ -15624,18 +16746,18 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +                              err = 0;
 +                              opt->type = token;
 +                      } else
-+                              AuErr("wrong value, %s\n", opt_str);
++                              pr_err("wrong value, %s\n", opt_str);
 +                      break;
 +
 +              case Opt_ignore:
-+                      AuWarn("ignored %s\n", opt_str);
++                      pr_warning("ignored %s\n", opt_str);
 +                      /*FALLTHROUGH*/
 +              case Opt_ignore_silent:
 +                      skipped = 1;
 +                      err = 0;
 +                      break;
 +              case Opt_err:
-+                      AuErr("unknown option %s\n", opt_str);
++                      pr_err("unknown option %s\n", opt_str);
 +                      break;
 +              }
 +
@@ -15958,14 +17080,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +
 +      if (!(sb_flags & MS_RDONLY)) {
 +              if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
-+                      AuWarn("first branch should be rw\n");
++                      pr_warning("first branch should be rw\n");
 +              if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
-+                      AuWarn("shwh should be used with ro\n");
++                      pr_warning("shwh should be used with ro\n");
 +      }
 +
-+      if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HINOTIFY)
++      if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
 +          && !au_opt_test(sbinfo->si_mntflags, XINO))
-+              AuWarn("udba=inotify requires xino\n");
++              pr_warning("udba=*notify requires xino\n");
 +
 +      err = 0;
 +      root = sb->s_root;
@@ -16026,13 +17148,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +                      continue;
 +
 +              hdir = au_hi(dir, bindex);
-+              au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++              au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
 +              if (wbr)
 +                      wbr_wh_write_lock(wbr);
 +              err = au_wh_init(au_h_dptr(root, bindex), br, sb);
 +              if (wbr)
 +                      wbr_wh_write_unlock(wbr);
-+              au_hin_imtx_unlock(hdir);
++              au_hn_imtx_unlock(hdir);
 +
 +              if (!err && do_free) {
 +                      kfree(wbr);
@@ -16081,7 +17203,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      bend = au_sbend(sb);
 +      if (unlikely(bend < 0)) {
 +              err = -EINVAL;
-+              AuErr("no branches\n");
++              pr_err("no branches\n");
 +              goto out;
 +      }
 +
@@ -16113,10 +17235,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +      /* restore udba */
 +      sbinfo->si_mntflags &= ~AuOptMask_UDBA;
 +      sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
-+      if (au_opt_test(tmp, UDBA_HINOTIFY)) {
++      if (au_opt_test(tmp, UDBA_HNOTIFY)) {
 +              struct inode *dir = sb->s_root->d_inode;
-+              au_reset_hinotify(dir,
-+                                au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
++              au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
 +      }
 +
 + out:
@@ -16176,12 +17297,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.c linux-2.6.31/fs/aufs/opts.c
 +{
 +      return au_mntflags(sb) & AuOptMask_UDBA;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.h linux-2.6.31/fs/aufs/opts.h
---- linux-2.6.31-vanilla/fs/aufs/opts.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/opts.h        2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/opts.h linux-2.6.33.1/fs/aufs/opts.h
+--- linux-2.6.33.1-vanilla/fs/aufs/opts.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/opts.h      2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,196 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -16221,7 +17342,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.h linux-2.6.31/fs/aufs/opts.h
 +#define AuOpt_TRUNC_XINO      (1 << 1)        /* truncate xino files */
 +#define AuOpt_UDBA_NONE               (1 << 2)        /* users direct branch access */
 +#define AuOpt_UDBA_REVAL      (1 << 3)
-+#define AuOpt_UDBA_HINOTIFY   (1 << 4)
++#define AuOpt_UDBA_HNOTIFY    (1 << 4)
 +#define AuOpt_SHWH            (1 << 5)        /* show whiteout */
 +#define AuOpt_PLINK           (1 << 6)        /* pseudo-link */
 +#define AuOpt_DIRPERM1                (1 << 7)        /* unimplemented */
@@ -16232,9 +17353,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.h linux-2.6.31/fs/aufs/opts.h
 +#define AuOpt_WARN_PERM               (1 << 12)       /* warn when add-branch */
 +#define AuOpt_VERBOSE         (1 << 13)       /* busy inode when del-branch */
 +
-+#ifndef CONFIG_AUFS_HINOTIFY
-+#undef AuOpt_UDBA_HINOTIFY
-+#define AuOpt_UDBA_HINOTIFY   0
++#ifndef CONFIG_AUFS_HNOTIFY
++#undef AuOpt_UDBA_HNOTIFY
++#define AuOpt_UDBA_HNOTIFY    0
 +#endif
 +#ifndef CONFIG_AUFS_SHWH
 +#undef AuOpt_SHWH
@@ -16248,7 +17369,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.h linux-2.6.31/fs/aufs/opts.h
 +                       | AuOpt_WARN_PERM)
 +#define AuOptMask_UDBA        (AuOpt_UDBA_NONE \
 +                       | AuOpt_UDBA_REVAL \
-+                       | AuOpt_UDBA_HINOTIFY)
++                       | AuOpt_UDBA_HNOTIFY)
 +
 +#define au_opt_test(flags, name)      (flags & AuOpt_##name)
 +#define au_opt_set(flags, name) do { \
@@ -16376,12 +17497,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/opts.h linux-2.6.31/fs/aufs/opts.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_OPTS_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/plink.c linux-2.6.31/fs/aufs/plink.c
---- linux-2.6.31-vanilla/fs/aufs/plink.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/plink.c       2009-09-16 13:55:29.000000000 +0200
-@@ -0,0 +1,396 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/plink.c linux-2.6.33.1/fs/aufs/plink.c
+--- linux-2.6.33.1-vanilla/fs/aufs/plink.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/plink.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,430 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -16408,14 +17529,53 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/plink.c linux-2.6.31/fs/aufs/plink.c
 + * during a user process maintains the pseudo-links,
 + * prohibit adding a new plink and branch manipulation.
 + */
-+void au_plink_block_maintain(struct super_block *sb)
++void au_plink_maint_block(struct super_block *sb)
 +{
 +      struct au_sbinfo *sbi = au_sbi(sb);
 +
 +      SiMustAnyLock(sb);
 +
 +      /* gave up wake_up_bit() */
-+      wait_event(sbi->si_plink_wq, !au_ftest_si(sbi, MAINTAIN_PLINK));
++      wait_event(sbi->si_plink_wq, !sbi->si_plink_maint);
++}
++
++void au_plink_maint_leave(struct file *file)
++{
++      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);
++      if (iam)
++              sbinfo->si_plink_maint = NULL;
++      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 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_unlock(sb);
++
++      return err;
 +}
 +
 +/* ---------------------------------------------------------------------- */
@@ -16654,14 +17814,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/plink.c linux-2.6.31/fs/aufs/plink.c
 +      spin_unlock(&sbinfo->si_plink.spin);
 +
 +      if (!err) {
-+              au_plink_block_maintain(sb);
++              au_plink_maint_block(sb);
 +              err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
 +      }
 +
 +      if (unlikely(cnt > AUFS_PLINK_WARN))
 +              AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
 +      if (unlikely(err)) {
-+              AuWarn("err %d, damaged pseudo link.\n", err);
++              pr_warning("err %d, damaged pseudo link.\n", err);
 +              if (!found && plink)
 +                      do_put_plink(plink, /*do_del*/1);
 +      }
@@ -16756,13 +17916,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/plink.c linux-2.6.31/fs/aufs/plink.c
 +               * pseudo-link maintenance mode,
 +               * cleared by aufs_release_dir()
 +               */
-+              si_write_lock(sb);
-+              if (!au_ftest_si(sbinfo, MAINTAIN_PLINK)) {
-+                      au_fset_si(sbinfo, MAINTAIN_PLINK);
-+                      au_fi(file)->fi_maintain_plink = 1;
-+              } else
-+                      err = -EBUSY;
-+              si_write_unlock(sb);
++              err = au_plink_maint_enter(file);
 +              break;
 +      case AUFS_CTL_PLINK_CLEAN:
 +              aufs_write_lock(sb->s_root);
@@ -16771,17 +17925,18 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/plink.c linux-2.6.31/fs/aufs/plink.c
 +              aufs_write_unlock(sb->s_root);
 +              break;
 +      default:
++              /* err = -ENOTTY; */
 +              err = -EINVAL;
 +      }
 + out:
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/poll.c linux-2.6.31/fs/aufs/poll.c
---- linux-2.6.31-vanilla/fs/aufs/poll.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/poll.c        2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/poll.c linux-2.6.33.1/fs/aufs/poll.c
+--- linux-2.6.33.1-vanilla/fs/aufs/poll.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/poll.c      2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,56 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -16836,12 +17991,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/poll.c linux-2.6.31/fs/aufs/poll.c
 +      AuTraceErr((int)mask);
 +      return mask;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/rdu.c linux-2.6.31/fs/aufs/rdu.c
---- linux-2.6.31-vanilla/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/rdu.c 2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,331 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/rdu.c linux-2.6.33.1/fs/aufs/rdu.c
+--- linux-2.6.33.1-vanilla/fs/aufs/rdu.c       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/rdu.c       2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,330 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -16862,6 +18017,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/rdu.c linux-2.6.31/fs/aufs/rdu.c
 + * readdir in userspace.
 + */
 +
++#include <linux/fs_stack.h>
 +#include <linux/security.h>
 +#include <linux/uaccess.h>
 +#include <linux/aufs_type.h>
@@ -16901,6 +18057,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/rdu.c linux-2.6.31/fs/aufs/rdu.c
 +              ent.bindex = rdu->cookie.bindex;
 +              ent.type = d_type;
 +              ent.nlen = nlen;
++              if (unlikely(nlen > AUFS_MAX_NAMELEN))
++                      ent.type = DT_UNKNOWN;
 +
 +              err = -EFAULT;
 +              if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
@@ -17071,14 +18229,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/rdu.c linux-2.6.31/fs/aufs/rdu.c
 +      sb = file->f_dentry->d_sb;
 +      si_read_lock(sb, AuLock_FLUSH);
 +      while (nent-- > 0) {
-+              err = !access_ok(VERIFY_WRITE, u->e, sizeof(ent));
-+              if (unlikely(err)) {
-+                      err = -EFAULT;
-+                      AuTraceErr(err);
-+                      break;
-+              }
-+
 +              err = copy_from_user(&ent, u->e, sizeof(ent));
++              if (!err)
++                      err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
 +              if (unlikely(err)) {
 +                      err = -EFAULT;
 +                      AuTraceErr(err);
@@ -17164,6 +18317,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/rdu.c linux-2.6.31/fs/aufs/rdu.c
 +              break;
 +
 +      default:
++              /* err = -ENOTTY; */
 +              err = -EINVAL;
 +      }
 +
@@ -17171,12 +18325,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/rdu.c linux-2.6.31/fs/aufs/rdu.c
 +      AuTraceErr(err);
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/rwsem.h linux-2.6.31/fs/aufs/rwsem.h
---- linux-2.6.31-vanilla/fs/aufs/rwsem.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/rwsem.h       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,186 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/rwsem.h linux-2.6.33.1/fs/aufs/rwsem.h
+--- linux-2.6.33.1-vanilla/fs/aufs/rwsem.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/rwsem.h     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,187 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -17203,6 +18357,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/rwsem.h linux-2.6.31/fs/aufs/rwsem.h
 +#ifdef __KERNEL__
 +
 +#include <linux/rwsem.h>
++#include "debug.h"
 +
 +struct au_rwsem {
 +      struct rw_semaphore     rwsem;
@@ -17361,12 +18516,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/rwsem.h linux-2.6.31/fs/aufs/rwsem.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_RWSEM_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/sbinfo.c linux-2.6.31/fs/aufs/sbinfo.c
---- linux-2.6.31-vanilla/fs/aufs/sbinfo.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/sbinfo.c      2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,208 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/sbinfo.c linux-2.6.33.1/fs/aufs/sbinfo.c
+--- linux-2.6.33.1-vanilla/fs/aufs/sbinfo.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/sbinfo.c    2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,202 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -17399,6 +18554,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sbinfo.c linux-2.6.31/fs/aufs/sbinfo.c
 +
 +      sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
 +      AuDebugOn(!list_empty(&sbinfo->si_plink.head));
++      AuDebugOn(sbinfo->si_plink_maint);
 +
 +      sb = sbinfo->si_sb;
 +      si_write_lock(sb);
@@ -17418,7 +18574,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sbinfo.c linux-2.6.31/fs/aufs/sbinfo.c
 +      struct au_sbinfo *sbinfo;
 +
 +      err = -ENOMEM;
-+      sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
++      sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
 +      if (unlikely(!sbinfo))
 +              goto out;
 +
@@ -17427,30 +18583,22 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sbinfo.c linux-2.6.31/fs/aufs/sbinfo.c
 +      if (unlikely(!sbinfo->si_branch))
 +              goto out_sbinfo;
 +
-+      memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
 +      err = sysaufs_si_init(sbinfo);
 +      if (unlikely(err))
 +              goto out_br;
 +
 +      au_nwt_init(&sbinfo->si_nowait);
 +      au_rw_init_wlock(&sbinfo->si_rwsem);
-+      sbinfo->si_generation = 0;
-+      sbinfo->au_si_status = 0;
 +      sbinfo->si_bend = -1;
-+      sbinfo->si_last_br_id = 0;
 +
 +      sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
 +      sbinfo->si_wbr_create = AuWbrCreate_Def;
-+      sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
-+      sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
++      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_xread = NULL;
-+      sbinfo->si_xwrite = NULL;
-+      sbinfo->si_xib = NULL;
 +      mutex_init(&sbinfo->si_xib_mtx);
-+      sbinfo->si_xib_buf = NULL;
 +      sbinfo->si_xino_brid = -1;
 +      /* leave si_xib_last_pindex and si_xib_next_bit */
 +
@@ -17461,6 +18609,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sbinfo.c linux-2.6.31/fs/aufs/sbinfo.c
 +
 +      au_spl_init(&sbinfo->si_plink);
 +      init_waitqueue_head(&sbinfo->si_plink_wq);
++      spin_lock_init(&sbinfo->si_plink_maint_lock);
 +
 +      /* leave other members for sysaufs and si_mnt. */
 +      sbinfo->si_sb = sb;
@@ -17573,12 +18722,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sbinfo.c linux-2.6.31/fs/aufs/sbinfo.c
 +      di_write_unlock2(d1, d2);
 +      si_read_unlock(d1->d_sb);
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/spl.h linux-2.6.31/fs/aufs/spl.h
---- linux-2.6.31-vanilla/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/spl.h 2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/spl.h linux-2.6.33.1/fs/aufs/spl.h
+--- linux-2.6.33.1-vanilla/fs/aufs/spl.h       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/spl.h       2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,57 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -17634,12 +18783,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/spl.h linux-2.6.31/fs/aufs/spl.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_SPL_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
---- linux-2.6.31-vanilla/fs/aufs/super.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/super.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,874 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/super.c linux-2.6.33.1/fs/aufs/super.c
+--- linux-2.6.33.1-vanilla/fs/aufs/super.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/super.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,838 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -17906,9 +19055,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +      si_read_unlock(sb);
 +      return 0;
 +
-+#undef Deleted
 +#undef AuBool
 +#undef AuStr
++#undef AuUInt
 +}
 +
 +/* ---------------------------------------------------------------------- */
@@ -17991,7 +19140,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +
 +      if (!err) {
 +              buf->f_type = AUFS_SUPER_MAGIC;
-+              buf->f_namelen -= AUFS_WH_PFX_LEN;
++              buf->f_namelen = AUFS_MAX_NAMELEN;
 +              memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
 +      }
 +      /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
@@ -18001,34 +19150,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +
 +/* ---------------------------------------------------------------------- */
 +
-+/* try flushing the lower fs at aufs remount/unmount time */
-+
-+static void au_fsync_br(struct super_block *sb)
-+{
-+      aufs_bindex_t bend, bindex;
-+      int brperm;
-+      struct au_branch *br;
-+      struct super_block *h_sb;
-+
-+      bend = au_sbend(sb);
-+      for (bindex = 0; bindex < bend; bindex++) {
-+              br = au_sbr(sb, bindex);
-+              brperm = br->br_perm;
-+              if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
-+                      continue;
-+              h_sb = br->br_mnt->mnt_sb;
-+              if (bdev_read_only(h_sb->s_bdev))
-+                      continue;
-+
-+              lockdep_off();
-+              down_write(&h_sb->s_umount);
-+              shrink_dcache_sb(h_sb);
-+              sync_filesystem(h_sb);
-+              up_write(&h_sb->s_umount);
-+              lockdep_on();
-+      }
-+}
-+
 +/*
 + * this IS NOT for super_operations.
 + * I guess it will be reverted someday.
@@ -18042,7 +19163,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +              return;
 +
 +      si_write_lock(sb);
-+      au_fsync_br(sb);
 +      if (au_opt_test(au_mntflags(sb), PLINK))
 +              au_plink_put(sb);
 +      if (sbinfo->si_wbr_create_ops->fin)
@@ -18085,10 +19205,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +              struct inode *inode = dentry->d_inode;
 +              err = au_refresh_hinode(inode, dentry);
 +              if (!err && type == S_IFDIR)
-+                      au_reset_hinotify(inode, dir_flags);
++                      au_hn_reset(inode, dir_flags);
 +      }
 +      if (unlikely(err))
-+              AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
++              pr_err("unrecoverable error %d, %.*s\n",
++                     err, AuDLNPair(dentry));
 +
 +      di_read_unlock(parent, AuLock_IR);
 +      dput(parent);
@@ -18250,20 +19371,21 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +      DiMustNoWaiters(root);
 +      inode = root->d_inode;
 +      IiMustNoWaiters(inode);
-+      au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
++      au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
 +      di_write_unlock(root);
 +
 +      err = refresh_dir(root, sigen);
 +      if (unlikely(err)) {
 +              au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
-+              AuWarn("Refreshing directories failed, ignored (%d)\n", err);
++              pr_warning("Refreshing directories failed, ignored (%d)\n",
++                         err);
 +      }
 +
 +      if (au_ftest_opts(flags, REFRESH_NONDIR)) {
 +              err = refresh_nondir(root, sigen, !err);
 +              if (unlikely(err))
-+                      AuWarn("Refreshing non-directories failed, ignored"
-+                             "(%d)\n", err);
++                      pr_warning("Refreshing non-directories failed, ignored"
++                                 "(%d)\n", err);
 +      }
 +
 +      /* aufs_write_lock() calls ..._child() */
@@ -18299,8 +19421,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +      if (!data || !*data) {
 +              aufs_write_lock(root);
 +              err = au_opts_verify(sb, *flags, /*pending*/0);
-+              if (!err)
-+                      au_fsync_br(sb);
 +              aufs_write_unlock(root);
 +              goto out;
 +      }
@@ -18323,7 +19443,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +      inode = root->d_inode;
 +      mutex_lock(&inode->i_mutex);
 +      aufs_write_lock(root);
-+      au_fsync_br(sb);
 +
 +      /* au_opts_remount() may return an error */
 +      err = au_opts_remount(sb, &opts);
@@ -18344,7 +19463,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +      return err;
 +}
 +
-+static struct super_operations aufs_sop = {
++static const struct super_operations aufs_sop = {
 +      .alloc_inode    = aufs_alloc_inode,
 +      .destroy_inode  = aufs_destroy_inode,
 +      .drop_inode     = generic_delete_inode,
@@ -18408,7 +19527,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +
 +      if (unlikely(!arg || !*arg)) {
 +              err = -EINVAL;
-+              AuErr("no arg\n");
++              pr_err("no arg\n");
 +              goto out;
 +      }
 +
@@ -18452,20 +19571,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +
 +      /* lock vfs_inode first, then aufs. */
 +      mutex_lock(&inode->i_mutex);
-+      inode->i_op = &aufs_dir_iop;
-+      inode->i_fop = &aufs_dir_fop;
 +      aufs_write_lock(root);
 +      err = au_opts_mount(sb, &opts);
 +      au_opts_free(&opts);
-+      if (unlikely(err))
-+              goto out_unlock;
 +      aufs_write_unlock(root);
 +      mutex_unlock(&inode->i_mutex);
-+      goto out_opts; /* success */
++      if (!err)
++              goto out_opts; /* success */
 +
-+ out_unlock:
-+      aufs_write_unlock(root);
-+      mutex_unlock(&inode->i_mutex);
 + out_root:
 +      dput(root);
 +      sb->s_root = NULL;
@@ -18512,12 +19625,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.c linux-2.6.31/fs/aufs/super.c
 +      /* no need to __module_get() and module_put(). */
 +      .owner          = THIS_MODULE,
 +};
-diff -Nur linux-2.6.31-vanilla/fs/aufs/super.h linux-2.6.31/fs/aufs/super.h
---- linux-2.6.31-vanilla/fs/aufs/super.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/super.h       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,384 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/super.h linux-2.6.33.1/fs/aufs/super.h
+--- linux-2.6.33.1-vanilla/fs/aufs/super.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/super.h     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,361 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -18647,6 +19760,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.h linux-2.6.31/fs/aufs/super.h
 +      /* pseudo_link list */
 +      struct au_splhead       si_plink;
 +      wait_queue_head_t       si_plink_wq;
++      spinlock_t              si_plink_maint_lock;
++      struct file             *si_plink_maint;
 +
 +      /*
 +       * sysfs and lifetime management.
@@ -18673,7 +19788,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.h linux-2.6.31/fs/aufs/super.h
 + * if it is false, refreshing dirs at access time is unnecesary
 + */
 +#define AuSi_FAILED_REFRESH_DIRS      1
-+#define AuSi_MAINTAIN_PLINK           (1 << 1)        /* ioctl */
 +static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
 +                                         unsigned int flag)
 +{
@@ -18693,10 +19807,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.h linux-2.6.31/fs/aufs/super.h
 +/* ---------------------------------------------------------------------- */
 +
 +/* policy to select one among writable branches */
-+#define AuWbrCopyup(sbinfo, args...) \
-+      ((sbinfo)->si_wbr_copyup_ops->copyup(args))
-+#define AuWbrCreate(sbinfo, args...) \
-+      ((sbinfo)->si_wbr_create_ops->create(args))
++#define AuWbrCopyup(sbinfo, ...) \
++      ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
++#define AuWbrCreate(sbinfo, ...) \
++      ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
 +
 +/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
 +#define AuLock_DW             1               /* write-lock dentry */
@@ -18763,36 +19877,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.h linux-2.6.31/fs/aufs/super.h
 +      return -ESTALE;
 +}
 +#else
-+static inline void au_export_init(struct super_block *sb)
-+{
-+      /* nothing */
-+}
-+
-+static inline int au_test_nfsd(struct task_struct *tsk)
-+{
-+      return 0;
-+}
-+
-+static inline int au_xigen_inc(struct inode *inode)
-+{
-+      return 0;
-+}
-+
-+static inline int au_xigen_new(struct inode *inode)
-+{
-+      return 0;
-+}
-+
-+static inline int au_xigen_set(struct super_block *sb, struct file *base)
-+{
-+      return 0;
-+}
-+
-+static inline void au_xigen_clr(struct super_block *sb)
-+{
-+      /* empty */
-+}
-+
++AuStubVoid(au_export_init, struct super_block *sb)
++AuStubInt0(au_test_nfsd, struct task_struct *tsk)
++AuStubInt0(au_xigen_inc, struct inode *inode)
++AuStubInt0(au_xigen_new, struct inode *inode)
++AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
++AuStubVoid(au_xigen_clr, struct super_block *sb)
 +static inline int au_busy_or_stale(void)
 +{
 +      return -EBUSY;
@@ -18900,12 +19990,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/super.h linux-2.6.31/fs/aufs/super.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_SUPER_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/sysaufs.c linux-2.6.31/fs/aufs/sysaufs.c
---- linux-2.6.31-vanilla/fs/aufs/sysaufs.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/sysaufs.c     2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,104 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/sysaufs.c linux-2.6.33.1/fs/aufs/sysaufs.c
+--- linux-2.6.33.1-vanilla/fs/aufs/sysaufs.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/sysaufs.c   2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,107 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -18992,7 +20082,10 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysaufs.c linux-2.6.31/fs/aufs/sysaufs.c
 +              get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
 +      } while (!sysaufs_si_mask);
 +
++      err = -EINVAL;
 +      sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
++      if (unlikely(!sysaufs_ket))
++              goto out;
 +      err = PTR_ERR(sysaufs_ket);
 +      if (IS_ERR(sysaufs_ket))
 +              goto out;
@@ -19008,12 +20101,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysaufs.c linux-2.6.31/fs/aufs/sysaufs.c
 + out:
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/sysaufs.h linux-2.6.31/fs/aufs/sysaufs.h
---- linux-2.6.31-vanilla/fs/aufs/sysaufs.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/sysaufs.h     2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,120 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/sysaufs.h linux-2.6.33.1/fs/aufs/sysaufs.h
+--- linux-2.6.33.1-vanilla/fs/aufs/sysaufs.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/sysaufs.h   2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,105 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -19095,11 +20188,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysaufs.h linux-2.6.31/fs/aufs/sysaufs.h
 +#else
 +#define sysaufs_attr_group    NULL
 +
-+static inline
-+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
-+{
-+      return 0;
-+}
++AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
 +
 +static inline
 +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
@@ -19108,20 +20197,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysaufs.h linux-2.6.31/fs/aufs/sysaufs.h
 +      return 0;
 +}
 +
-+static inline void sysaufs_br_init(struct au_branch *br)
-+{
-+      /* empty */
-+}
-+
-+static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+      /* nothing */
-+}
-+
-+static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+      /* nothing */
-+}
++AuStubVoid(sysaufs_br_init, struct au_branch *br)
++AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
++AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
 +
 +static inline void sysaufs_brs_init(void)
 +{
@@ -19132,12 +20210,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysaufs.h linux-2.6.31/fs/aufs/sysaufs.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __SYSAUFS_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/sysfs.c linux-2.6.31/fs/aufs/sysfs.c
---- linux-2.6.31-vanilla/fs/aufs/sysfs.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/sysfs.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,210 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/sysfs.c linux-2.6.33.1/fs/aufs/sysfs.c
+--- linux-2.6.33.1-vanilla/fs/aufs/sysfs.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/sysfs.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,248 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -19164,7 +20242,30 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysfs.c linux-2.6.31/fs/aufs/sysfs.c
 +#include <linux/sysfs.h>
 +#include "aufs.h"
 +
++#ifdef CONFIG_AUFS_FS_MODULE
++/* this entry violates the "one line per file" policy of sysfs */
++static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
++                         char *buf)
++{
++      ssize_t err;
++      static char *conf =
++/* this file is generated at compiling */
++#include "conf.str"
++              ;
++
++      err = snprintf(buf, PAGE_SIZE, conf);
++      if (unlikely(err >= PAGE_SIZE))
++              err = -EFBIG;
++      return err;
++}
++
++static struct kobj_attribute au_config_attr = __ATTR_RO(config);
++#endif
++
 +static struct attribute *au_attr[] = {
++#ifdef CONFIG_AUFS_FS_MODULE
++      &au_config_attr.attr,
++#endif
 +      NULL,   /* need to NULL terminate the list of attributes */
 +};
 +
@@ -19237,7 +20338,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysfs.c linux-2.6.31/fs/aufs/sysfs.c
 +
 +/* todo: file size may exceed PAGE_SIZE */
 +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
-+                       char *buf)
++                      char *buf)
 +{
 +      ssize_t err;
 +      long l;
@@ -19250,12 +20351,25 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysfs.c linux-2.6.31/fs/aufs/sysfs.c
 +
 +      sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
 +      sb = sbinfo->si_sb;
-+      si_noflush_read_lock(sb);
++
++      /*
++       * prevent a race condition between sysfs and aufs.
++       * for instance, sysfs_file_read() calls sysfs_get_active_two() which
++       * prohibits maintaining the sysfs entries.
++       * hew we acquire read lock after sysfs_get_active_two().
++       * on the other hand, the remount process may maintain the sysfs/aufs
++       * entries after acquiring write lock.
++       * it can cause a deadlock.
++       * simply we gave up processing read here.
++       */
++      err = -EBUSY;
++      if (unlikely(!si_noflush_read_trylock(sb)))
++              goto out;
 +
 +      seq = au_seq(buf, PAGE_SIZE);
 +      err = PTR_ERR(seq);
 +      if (IS_ERR(seq))
-+              goto out;
++              goto out_unlock;
 +
 +      name = (void *)attr->name;
 +      cattr = sysaufs_si_attrs;
@@ -19290,8 +20404,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysfs.c linux-2.6.31/fs/aufs/sysfs.c
 +                      err = -EFBIG;
 +      }
 +      kfree(seq);
-+ out:
++ out_unlock:
 +      si_read_unlock(sb);
++ out:
 +      return err;
 +}
 +
@@ -19343,15 +20458,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysfs.c linux-2.6.31/fs/aufs/sysfs.c
 +                       "%d", bindex);
 +              err = sysfs_create_file(kobj, &br->br_attr);
 +              if (unlikely(err))
-+                      AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
++                      pr_warning("failed %s under sysfs(%d)\n",
++                                 br->br_name, err);
 +      }
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/sysrq.c linux-2.6.31/fs/aufs/sysrq.c
---- linux-2.6.31-vanilla/fs/aufs/sysrq.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/sysrq.c       2009-09-16 13:55:29.000000000 +0200
-@@ -0,0 +1,115 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/sysrq.c linux-2.6.33.1/fs/aufs/sysrq.c
+--- linux-2.6.33.1-vanilla/fs/aufs/sysrq.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/sysrq.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,119 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -19391,24 +20507,28 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysrq.c linux-2.6.31/fs/aufs/sysrq.c
 +      au_debug(1);
 +
 +      sbinfo = au_sbi(sb);
-+      pr_warning("si=%lx\n", sysaufs_si_id(sbinfo));
-+      pr_warning(AUFS_NAME ": superblock\n");
++      /* since we define pr_fmt, call printk directly */
++      printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
++      printk(KERN_WARNING AUFS_NAME ": superblock\n");
 +      au_dpri_sb(sb);
-+      pr_warning(AUFS_NAME ": root dentry\n");
++      printk(KERN_WARNING AUFS_NAME ": root dentry\n");
 +      au_dpri_dentry(sb->s_root);
-+      pr_warning(AUFS_NAME ": root inode\n");
++      printk(KERN_WARNING AUFS_NAME ": root inode\n");
 +      au_dpri_inode(sb->s_root->d_inode);
 +#if 0
 +      struct inode *i;
-+      pr_warning(AUFS_NAME ": isolated inode\n");
++      printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
 +      list_for_each_entry(i, &sb->s_inodes, i_sb_list)
 +              if (list_empty(&i->i_dentry))
 +                      au_dpri_inode(i);
 +#endif
-+      pr_warning(AUFS_NAME ": files\n");
-+      list_for_each_entry(file, &sb->s_files, f_u.fu_list)
-+              if (!special_file(file->f_dentry->d_inode->i_mode))
++      printk(KERN_WARNING AUFS_NAME ": files\n");
++      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);
++      }
 +
 +      au_plevel = plevel;
 +      au_debug(0);
@@ -19454,7 +20574,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysrq.c linux-2.6.31/fs/aufs/sysrq.c
 +      if ('a' <= key && key <= 'z')
 +              err = register_sysrq_key(key, &au_sysrq_op);
 +      if (unlikely(err))
-+              AuErr("err %d, sysrq=%c\n", err, key);
++              pr_err("err %d, sysrq=%c\n", err, key);
 +      return err;
 +}
 +
@@ -19463,14 +20583,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/sysrq.c linux-2.6.31/fs/aufs/sysrq.c
 +      int err;
 +      err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
 +      if (unlikely(err))
-+              AuErr("err %d (ignored)\n", err);
++              pr_err("err %d (ignored)\n", err);
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
---- linux-2.6.31-vanilla/fs/aufs/vdir.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/vdir.c        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,879 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/vdir.c linux-2.6.33.1/fs/aufs/vdir.c
+--- linux-2.6.33.1-vanilla/fs/aufs/vdir.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/vdir.c      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,884 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -19496,7 +20616,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +
 +static unsigned int calc_size(int nlen)
 +{
-+      BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
 +      return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
 +}
 +
@@ -19538,7 +20657,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +              n = sz;
 +      if (sz < AUFS_RDHASH_DEF)
 +              n = AUFS_RDHASH_DEF;
-+      /* AuInfo("n %u\n", n); */
++      /* pr_info("n %u\n", n); */
 +      return n;
 +}
 +
@@ -19572,7 +20691,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +      n = 0;
 +      hlist_for_each(pos, head)
 +              n++;
-+      AuInfo("%lu\n", n);
++      pr_info("%lu\n", n);
 +#endif
 +}
 +
@@ -19594,7 +20713,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +
 +      hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
 +              /* hlist_del(pos); */
-+              au_cache_free_dehstr(tpos);
++              au_cache_free_vdir_dehstr(tpos);
 +      }
 +}
 +
@@ -19804,7 +20923,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +      }
 +
 +      err = -ENOMEM;
-+      dehstr = au_cache_alloc_dehstr();
++      dehstr = au_cache_alloc_vdir_dehstr();
 +      if (unlikely(!dehstr))
 +              goto out;
 +
@@ -19860,7 +20979,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +      if (!vdir->vd_deblk_sz) {
 +              /* estimate the apropriate size for deblk */
 +              vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
-+              /* AuInfo("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
++              /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
 +      }
 +      vdir->vd_nblk = 0;
 +      vdir->vd_version = 0;
@@ -19946,9 +21065,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +
 +              sb = arg->file->f_dentry->d_sb;
 +              arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
-+              if (!arg->err)
++              if (!arg->err) {
++                      if (unlikely(nlen > AUFS_MAX_NAMELEN))
++                              d_type = DT_UNKNOWN;
 +                      arg->err = append_de(arg->vdir, name, nlen, ino,
 +                                           d_type, &arg->delist);
++              }
 +      } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
 +              name += AUFS_WH_PFX_LEN;
 +              nlen -= AUFS_WH_PFX_LEN;
@@ -19958,10 +21080,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +              if (shwh)
 +                      arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
 +                                           &ino);
-+              if (!arg->err)
++              if (!arg->err) {
++                      if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
++                              d_type = DT_UNKNOWN;
 +                      arg->err = au_nhash_append_wh
 +                              (&arg->whlist, name, nlen, ino, d_type,
 +                               arg->bindex, shwh);
++              }
 +      }
 +
 + out:
@@ -19987,7 +21112,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +      AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
 +
 +      err = -ENOMEM;
-+      o = p = __getname();
++      o = p = __getname_gfp(GFP_NOFS);
 +      if (unlikely(!p))
 +              goto out;
 +
@@ -20348,12 +21473,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vdir.c linux-2.6.31/fs/aufs/vdir.c
 +      /* smp_mb(); */
 +      return 0;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
---- linux-2.6.31-vanilla/fs/aufs/vfsub.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/vfsub.c       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,755 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/vfsub.c linux-2.6.33.1/fs/aufs/vfsub.c
+--- linux-2.6.33.1-vanilla/fs/aufs/vfsub.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/vfsub.c     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,790 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -20374,6 +21499,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 + * sub-routines for VFS
 + */
 +
++#include <linux/file.h>
 +#include <linux/ima.h>
 +#include <linux/namei.h>
 +#include <linux/security.h>
@@ -20403,20 +21529,49 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +
 +/* ---------------------------------------------------------------------- */
 +
++static int au_conv_oflags(int flags)
++{
++      int mask = 0;
++
 +#ifdef CONFIG_IMA
-+#error IMA is not supported since it does not work well. Wait for their fixing.
++      fmode_t fmode;
++
++      /* mask = MAY_OPEN; */
++      fmode = OPEN_FMODE(flags);
++      if (fmode & FMODE_READ)
++              mask |= MAY_READ;
++      if ((fmode & FMODE_WRITE)
++          || (flags & O_TRUNC))
++              mask |= MAY_WRITE;
++      /*
++       * if (flags & O_APPEND)
++       *      mask |= MAY_APPEND;
++       */
++      if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
++              mask |= MAY_EXEC;
++
++      AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
 +#endif
 +
-+struct file *vfsub_dentry_open(struct path *path, int flags,
-+                             const struct cred *cred)
++      return mask;
++}
++
++struct file *vfsub_dentry_open(struct path *path, int flags)
 +{
 +      struct file *file;
++      int err;
 +
-+      file = dentry_open(path->dentry, path->mnt, flags, cred);
++      path_get(path);
++      file = dentry_open(path->dentry, path->mnt, flags, current_cred());
 +      if (IS_ERR(file))
-+              return file;
-+      /* as NFSD does, just call ima_..._get() simply after dentry_open */
-+      ima_counts_get(file);
++              goto out;
++
++      err = ima_file_check(file, au_conv_oflags(flags));
++      if (unlikely(err)) {
++              fput(file);
++              file = ERR_PTR(err);
++      }
++out:
 +      return file;
 +}
 +
@@ -20424,9 +21579,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +{
 +      struct file *file;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      file = filp_open(path, oflags, mode);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (IS_ERR(file))
 +              goto out;
 +      vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
@@ -20464,6 +21619,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +              vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
 +
 + out:
++      AuTraceErrPtr(path.dentry);
 +      return path.dentry;
 +}
 +
@@ -20476,9 +21632,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +      IMustLock(nd->path.dentry->d_inode);
 +
 +      path.dentry = lookup_hash(nd);
-+      if (!IS_ERR(path.dentry) && path.dentry->d_inode)
++      if (IS_ERR(path.dentry))
++              goto out;
++      if (path.dentry->d_inode)
 +              vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
 +
++ out:
++      AuTraceErrPtr(path.dentry);
 +      return path.dentry;
 +}
 +
@@ -20492,9 +21652,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +      lockdep_off();
 +      d = lock_rename(d1, d2);
 +      lockdep_on();
-+      au_hin_suspend(hdir1);
++      au_hn_suspend(hdir1);
 +      if (hdir1 != hdir2)
-+              au_hin_suspend(hdir2);
++              au_hn_suspend(hdir2);
 +
 +      return d;
 +}
@@ -20502,9 +21662,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
 +                       struct dentry *d2, struct au_hinode *hdir2)
 +{
-+      au_hin_resume(hdir1);
++      au_hn_resume(hdir1);
 +      if (hdir1 != hdir2)
-+              au_hin_resume(hdir2);
++              au_hn_resume(hdir2);
 +      lockdep_off();
 +      unlock_rename(d1, d2);
 +      lockdep_on();
@@ -20649,9 +21809,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +      if (unlikely(err))
 +              goto out;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = vfs_link(src_dentry, dir, path->dentry);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (!err) {
 +              struct path tmp = *path;
 +              int did;
@@ -20691,9 +21851,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +      if (unlikely(err))
 +              goto out;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (!err) {
 +              int did;
 +
@@ -20757,9 +21917,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +      if (unlikely(err))
 +              goto out;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = vfs_rmdir(dir, path->dentry);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (!err) {
 +              struct path tmp = {
 +                      .dentry = path->dentry->d_parent,
@@ -20805,9 +21965,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +{
 +      ssize_t err;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = vfs_write(file, ubuf, count, ppos);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (err >= 0)
 +              vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
 +      return err;
@@ -20829,9 +21989,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +{
 +      int err;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = vfs_readdir(file, filldir, arg);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (err >= 0)
 +              vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
 +      return err;
@@ -20843,9 +22003,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +{
 +      long err;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = do_splice_to(in, ppos, pipe, len, flags);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (err >= 0)
 +              vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
 +      return err;
@@ -20856,9 +22016,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +{
 +      long err;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = do_splice_from(pipe, out, ppos, len, flags);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (err >= 0)
 +              vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
 +      return err;
@@ -20891,9 +22051,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +      if (!err)
 +              err = security_path_truncate(h_path, length, attr);
 +      if (!err) {
-+              lockdep_off();
++              /* lockdep_off(); */
 +              err = do_truncate(h_path->dentry, length, attr, h_file);
-+              lockdep_on();
++              /* lockdep_on(); */
 +      }
 +
 + out_inode:
@@ -20994,9 +22154,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +
 +      *a->errp = -EPERM;
 +      if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
-+              lockdep_off();
++              /* lockdep_off(); */
 +              *a->errp = notify_change(a->path->dentry, a->ia);
-+              lockdep_on();
++              /* lockdep_on(); */
 +              if (!*a->errp)
 +                      vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
 +      }
@@ -21063,9 +22223,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +      if (h_inode)
 +              atomic_inc(&h_inode->i_count);
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      *a->errp = vfs_unlink(a->dir, d);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      if (!*a->errp) {
 +              struct path tmp = {
 +                      .dentry = d->d_parent,
@@ -21107,12 +22267,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.c linux-2.6.31/fs/aufs/vfsub.c
 +
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.h linux-2.6.31/fs/aufs/vfsub.h
---- linux-2.6.31-vanilla/fs/aufs/vfsub.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/vfsub.h       2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,172 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/vfsub.h linux-2.6.33.1/fs/aufs/vfsub.h
+--- linux-2.6.33.1-vanilla/fs/aufs/vfsub.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/vfsub.h     2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,175 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -21139,7 +22299,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.h linux-2.6.31/fs/aufs/vfsub.h
 +#ifdef __KERNEL__
 +
 +#include <linux/fs.h>
-+#include <linux/fs_stack.h>
 +
 +/* ---------------------------------------------------------------------- */
 +
@@ -21162,18 +22321,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.h linux-2.6.31/fs/aufs/vfsub.h
 +
 +/* ---------------------------------------------------------------------- */
 +
-+static inline void vfsub_copy_inode_size(struct inode *inode,
-+                                       struct inode *h_inode)
-+{
-+      spin_lock(&inode->i_lock);
-+      fsstack_copy_inode_size(inode, h_inode);
-+      spin_unlock(&inode->i_lock);
-+}
-+
 +int vfsub_update_h_iattr(struct path *h_path, int *did);
++struct file *vfsub_dentry_open(struct path *path, int flags);
 +struct file *vfsub_filp_open(const char *path, int oflags, int mode);
-+struct file *vfsub_dentry_open(struct path *path, int flags,
-+                             const struct cred *cred);
 +int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
 +struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
 +                                  int len);
@@ -21198,12 +22348,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.h linux-2.6.31/fs/aufs/vfsub.h
 +int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
 +int vfsub_rmdir(struct inode *dir, struct path *path);
 +
-+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
-+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
-+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
-+int vfsub_notify_change(struct path *path, struct iattr *ia);
-+int vfsub_unlink(struct inode *dir, struct path *path, int force);
-+
 +/* ---------------------------------------------------------------------- */
 +
 +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
@@ -21216,13 +22360,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.h linux-2.6.31/fs/aufs/vfsub.h
 +                    loff_t *ppos);
 +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
 +
-+long vfsub_splice_to(struct file *in, loff_t *ppos,
-+                   struct pipe_inode_info *pipe, size_t len,
-+                   unsigned int flags);
-+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
-+                     loff_t *ppos, size_t len, unsigned int flags);
-+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
-+              struct file *h_file);
++static inline unsigned int vfsub_file_flags(struct file *file)
++{
++      unsigned int flags;
++
++      spin_lock(&file->f_lock);
++      flags = file->f_flags;
++      spin_unlock(&file->f_lock);
++
++      return flags;
++}
 +
 +static inline void vfsub_file_accessed(struct file *h_file)
 +{
@@ -21241,15 +22388,23 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.h linux-2.6.31/fs/aufs/vfsub.h
 +      vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
 +}
 +
++long vfsub_splice_to(struct file *in, loff_t *ppos,
++                   struct pipe_inode_info *pipe, size_t len,
++                   unsigned int flags);
++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                     loff_t *ppos, size_t len, unsigned int flags);
++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
++              struct file *h_file);
++
 +/* ---------------------------------------------------------------------- */
 +
 +static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
 +{
 +      loff_t err;
 +
-+      lockdep_off();
++      /* lockdep_off(); */
 +      err = vfs_llseek(file, offset, origin);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      return err;
 +}
 +
@@ -21281,14 +22436,22 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/vfsub.h linux-2.6.31/fs/aufs/vfsub.h
 +      return u.fm;
 +}
 +
++/* ---------------------------------------------------------------------- */
++
++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
++int vfsub_sio_rmdir(struct inode *dir, struct path *path);
++int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
++int vfsub_notify_change(struct path *path, struct iattr *ia);
++int vfsub_unlink(struct inode *dir, struct path *path, int force);
++
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_VFSUB_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/wbr_policy.c linux-2.6.31/fs/aufs/wbr_policy.c
---- linux-2.6.31-vanilla/fs/aufs/wbr_policy.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/wbr_policy.c  2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,641 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/wbr_policy.c linux-2.6.33.1/fs/aufs/wbr_policy.c
+--- linux-2.6.33.1-vanilla/fs/aufs/wbr_policy.c        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/wbr_policy.c        2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,637 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -21398,8 +22561,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wbr_policy.c linux-2.6.31/fs/aufs/wbr_pol
 +                       struct dentry *h_parent, void *arg)
 +{
 +      int err, rerr;
-+      aufs_bindex_t bend, bopq, bstart;
-+      unsigned char parent_opq;
++      aufs_bindex_t bopq, bstart;
 +      struct path h_path;
 +      struct dentry *parent;
 +      struct inode *h_dir, *h_inode, *inode, *dir;
@@ -21424,7 +22586,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wbr_policy.c linux-2.6.31/fs/aufs/wbr_pol
 +              goto out_put;
 +      au_fset_cpdown(args->flags, MADE_DIR);
 +
-+      bend = au_dbend(dentry);
 +      bopq = au_dbdiropq(dentry);
 +      au_fclr_cpdown(args->flags, WHED);
 +      au_fclr_cpdown(args->flags, DIROPQ);
@@ -21432,8 +22593,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wbr_policy.c linux-2.6.31/fs/aufs/wbr_pol
 +              au_fset_cpdown(args->flags, WHED);
 +      if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
 +              au_fset_cpdown(args->flags, PARENT_OPQ);
-+      parent_opq = (au_ftest_cpdown(args->flags, PARENT_OPQ)
-+                    && args->parent == dentry);
 +      h_inode = h_path.dentry->d_inode;
 +      mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
 +      if (au_ftest_cpdown(args->flags, WHED)) {
@@ -21928,12 +23087,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wbr_policy.c linux-2.6.31/fs/aufs/wbr_pol
 +              .fin    = au_wbr_create_fin_mfs
 +      }
 +};
-diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
---- linux-2.6.31-vanilla/fs/aufs/whout.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/whout.c       2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/whout.c linux-2.6.33.1/fs/aufs/whout.c
+--- linux-2.6.33.1-vanilla/fs/aufs/whout.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/whout.c     2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,1052 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -22006,9 +23165,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +{
 +      int err;
 +      struct dentry *wh_dentry;
-+      struct inode *h_dir;
 +
-+      h_dir = h_parent->d_inode;
 +      if (!try_sio)
 +              wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
 +      else
@@ -22055,19 +23212,20 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
 +                           struct qstr *prefix)
 +{
-+#define HEX_LEN       4
 +      struct dentry *dentry;
 +      int i;
-+      char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
-+                   + HEX_LEN + 1], *name, *p;
++      char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
++              *name, *p;
 +      static unsigned short cnt;
 +      struct qstr qs;
 +
++      BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
++
 +      name = defname;
 +      qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
 +      if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
 +              dentry = ERR_PTR(-ENAMETOOLONG);
-+              if (unlikely(qs.len >= PATH_MAX))
++              if (unlikely(qs.len > NAME_MAX))
 +                      goto out;
 +              dentry = ERR_PTR(-ENOMEM);
 +              name = kmalloc(qs.len + 1, GFP_NOFS);
@@ -22081,17 +23239,17 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      memcpy(p, prefix->name, prefix->len);
 +      p += prefix->len;
 +      *p++ = '.';
-+      AuDebugOn(name + qs.len + 1 - p <= HEX_LEN);
++      AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
 +
 +      qs.name = name;
 +      for (i = 0; i < 3; i++) {
-+              sprintf(p, "%.*d", HEX_LEN, cnt++);
++              sprintf(p, "%.*d", AUFS_WH_TMP_LEN, cnt++);
 +              dentry = au_sio_lkup_one(&qs, h_parent, br);
 +              if (IS_ERR(dentry) || !dentry->d_inode)
 +                      goto out_name;
 +              dput(dentry);
 +      }
-+      /* AuWarn("could not get random name\n"); */
++      /* pr_warning("could not get random name\n"); */
 +      dentry = ERR_PTR(-EEXIST);
 +      AuDbg("%.*s\n", AuLNPair(&qs));
 +      BUG();
@@ -22100,8 +23258,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      if (name != defname)
 +              kfree(name);
 + out:
++      AuTraceErrPtr(dentry);
 +      return dentry;
-+#undef HEX_LEN
 +}
 +
 +/*
@@ -22131,6 +23289,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      dput(h_path.dentry);
 +
 + out:
++      AuTraceErr(err);
 +      return err;
 +}
 +
@@ -22208,8 +23367,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +              mnt_drop_write(whpath->mnt);
 +      }
 +      if (unlikely(err))
-+              AuWarn("failed removing %.*s (%d), ignored.\n",
-+                     AuDLNPair(whpath->dentry), err);
++              pr_warning("failed removing %.*s (%d), ignored.\n",
++                         AuDLNPair(whpath->dentry), err);
 +}
 +
 +static int test_linkable(struct dentry *h_root)
@@ -22219,8 +23378,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      if (h_dir->i_op->link)
 +              return 0;
 +
-+      AuErr("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
-+            AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++      pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
++             AuDLNPair(h_root), au_sbtype(h_root->d_sb));
 +      return -ENOSYS;
 +}
 +
@@ -22243,7 +23402,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      } else if (S_ISDIR(path->dentry->d_inode->i_mode))
 +              err = 0;
 +      else
-+              AuErr("unknown %.*s exists\n", AuDLNPair(path->dentry));
++              pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
 +
 +      return err;
 +}
@@ -22342,8 +23501,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
 +              err = 0;
 +      else
-+              AuErr("unknown %.*s/%.*s exists\n",
-+                    AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
++              pr_err("unknown %.*s/%.*s exists\n",
++                     AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
 +      if (unlikely(err))
 +              goto out;
 +
@@ -22413,7 +23572,6 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      if (wbr)
 +              WbrWhMustWriteLock(wbr);
 +
-+      h_dir = h_root->d_inode;
 +      for (i = 0; i < AuBrWh_Last; i++) {
 +              /* doubly whiteouted */
 +              struct dentry *d;
@@ -22436,12 +23594,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +              }
 +
 +      err = 0;
-+
 +      switch (br->br_perm) {
 +      case AuBrPerm_RO:
 +      case AuBrPerm_ROWH:
 +      case AuBrPerm_RR:
 +      case AuBrPerm_RRWH:
++              h_dir = h_root->d_inode;
 +              au_wh_init_ro(h_dir, base, &path);
 +              break;
 +
@@ -22467,8 +23625,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      goto out; /* success */
 +
 + out_err:
-+      AuErr("an error(%d) on the writable branch %.*s(%s)\n",
-+            err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++      pr_err("an error(%d) on the writable branch %.*s(%s)\n",
++             err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
 + out:
 +      for (i = 0; i < AuBrWh_Last; i++)
 +              dput(base[i].dentry);
@@ -22513,7 +23671,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      hdir = au_hi(dir, bindex);
 +      h_root = au_h_dptr(a->sb->s_root, bindex);
 +
-+      au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++      au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
 +      wbr_wh_write_lock(wbr);
 +      err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
 +                        h_root, a->br);
@@ -22526,7 +23684,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +                      mnt_drop_write(a->br->br_mnt);
 +              }
 +      } else {
-+              AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase));
++              pr_warning("%.*s is moved, ignored\n",
++                         AuDLNPair(wbr->wbr_whbase));
 +              err = 0;
 +      }
 +      dput(wbr->wbr_whbase);
@@ -22534,7 +23693,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      if (!err)
 +              err = au_wh_init(h_root, a->br, a->sb);
 +      wbr_wh_write_unlock(wbr);
-+      au_hin_imtx_unlock(hdir);
++      au_hn_imtx_unlock(hdir);
 +      di_read_unlock(a->sb->s_root, AuLock_IR);
 +
 + out:
@@ -22768,7 +23927,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      struct au_vdir_destr *str;
 +
 +      err = -ENOMEM;
-+      p = __getname();
++      p = __getname_gfp(GFP_NOFS);
 +      wh_name.name = p;
 +      if (unlikely(!wh_name.name))
 +              goto out;
@@ -22914,8 +24073,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +              return 0; /* success */
 +      }
 +
-+      AuWarn("failed removing %.*s(%d), ignored\n",
-+             AuDLNPair(wh_dentry), err);
++      pr_warning("failed removing %.*s(%d), ignored\n",
++                 AuDLNPair(wh_dentry), err);
 +      return err;
 +}
 +
@@ -22943,7 +24102,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      h_parent = dget_parent(a->wh_dentry);
 +      h_dir = h_parent->d_inode;
 +      hdir = au_hi(a->dir, a->bindex);
-+      au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++      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);
 +      if (!err) {
 +              err = mnt_want_write(br->br_mnt);
@@ -22953,7 +24112,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +                      mnt_drop_write(br->br_mnt);
 +              }
 +      }
-+      au_hin_imtx_unlock(hdir);
++      au_hn_imtx_unlock(hdir);
 +      dput(h_parent);
 +      ii_write_unlock(a->dir);
 +
@@ -22979,17 +24138,17 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.c linux-2.6.31/fs/aufs/whout.c
 +      args->wh_dentry = dget(wh_dentry);
 +      wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
 +      if (unlikely(wkq_err)) {
-+              AuWarn("rmdir error %.*s (%d), ignored\n",
-+                     AuDLNPair(wh_dentry), wkq_err);
++              pr_warning("rmdir error %.*s (%d), ignored\n",
++                         AuDLNPair(wh_dentry), wkq_err);
 +              au_whtmp_rmdir_free(args);
 +      }
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.h linux-2.6.31/fs/aufs/whout.h
---- linux-2.6.31-vanilla/fs/aufs/whout.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/whout.h       2009-09-16 13:55:30.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/whout.h linux-2.6.33.1/fs/aufs/whout.h
+--- linux-2.6.33.1-vanilla/fs/aufs/whout.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/whout.h     2010-04-05 16:53:27.000000000 +0200
 @@ -0,0 +1,87 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -23075,12 +24234,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/whout.h linux-2.6.31/fs/aufs/whout.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_WHOUT_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.c linux-2.6.31/fs/aufs/wkq.c
---- linux-2.6.31-vanilla/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/wkq.c 2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,259 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/wkq.c linux-2.6.33.1/fs/aufs/wkq.c
+--- linux-2.6.33.1-vanilla/fs/aufs/wkq.c       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/wkq.c       2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,183 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -23106,12 +24265,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.c linux-2.6.31/fs/aufs/wkq.c
 +#include "aufs.h"
 +
 +/* internal workqueue named AUFS_WKQ_NAME */
-+static struct au_wkq {
-+      struct workqueue_struct *q;
-+
-+      /* balancing */
-+      atomic_t                busy;
-+} *au_wkq;
++static struct workqueue_struct *au_wkq;
 +
 +struct au_wkinfo {
 +      struct work_struct wk;
@@ -23122,60 +24276,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.c linux-2.6.31/fs/aufs/wkq.c
 +      au_wkq_func_t func;
 +      void *args;
 +
-+      atomic_t *busyp;
 +      struct completion *comp;
 +};
 +
 +/* ---------------------------------------------------------------------- */
 +
-+static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
-+{
-+      wkinfo->busyp = &wkq->busy;
-+      if (au_ftest_wkq(wkinfo->flags, WAIT))
-+              return !queue_work(wkq->q, &wkinfo->wk);
-+      else
-+              return !schedule_work(&wkinfo->wk);
-+}
-+
-+static void do_wkq(struct au_wkinfo *wkinfo)
-+{
-+      unsigned int idle, n;
-+      int i, idle_idx;
-+
-+      while (1) {
-+              if (au_ftest_wkq(wkinfo->flags, WAIT)) {
-+                      idle_idx = 0;
-+                      idle = UINT_MAX;
-+                      for (i = 0; i < aufs_nwkq; i++) {
-+                              n = atomic_inc_return(&au_wkq[i].busy);
-+                              if (n == 1 && !enqueue(au_wkq + i, wkinfo))
-+                                      return; /* success */
-+
-+                              if (n < idle) {
-+                                      idle_idx = i;
-+                                      idle = n;
-+                              }
-+                              atomic_dec(&au_wkq[i].busy);
-+                      }
-+              } else
-+                      idle_idx = aufs_nwkq;
-+
-+              atomic_inc(&au_wkq[idle_idx].busy);
-+              if (!enqueue(au_wkq + idle_idx, wkinfo))
-+                      return; /* success */
-+
-+              /* impossible? */
-+              AuWarn1("failed to queue_work()\n");
-+              yield();
-+      }
-+}
-+
 +static void wkq_func(struct work_struct *wk)
 +{
 +      struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
 +
 +      wkinfo->func(wkinfo->args);
-+      atomic_dec_return(wkinfo->busyp);
 +      if (au_ftest_wkq(wkinfo->flags, WAIT))
 +              complete(wkinfo->comp);
 +      else {
@@ -23226,11 +24336,16 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.c linux-2.6.31/fs/aufs/wkq.c
 +}
 +#endif /* 4KSTACKS */
 +
-+static void au_wkq_run(struct au_wkinfo *wkinfo)
++static void au_wkq_run(struct au_wkinfo *wkinfo, int do_wait)
 +{
 +      au_dbg_verify_kthread();
-+      INIT_WORK(&wkinfo->wk, wkq_func);
-+      do_wkq(wkinfo);
++      if (do_wait) {
++              INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
++              queue_work(au_wkq, &wkinfo->wk);
++      } else {
++              INIT_WORK(&wkinfo->wk, wkq_func);
++              schedule_work(&wkinfo->wk);
++      }
 +}
 +
 +int au_wkq_wait(au_wkq_func_t func, void *args)
@@ -23245,10 +24360,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.c linux-2.6.31/fs/aufs/wkq.c
 +
 +      err = au_wkq_comp_alloc(&wkinfo, &comp);
 +      if (!err) {
-+              au_wkq_run(&wkinfo);
++              au_wkq_run(&wkinfo, AuWkq_WAIT);
 +              /* no timeout, no interrupt */
 +              wait_for_completion(wkinfo.comp);
 +              au_wkq_comp_free(comp);
++              destroy_work_on_stack(&wkinfo.wk);
 +      }
 +
 +      return err;
@@ -23277,7 +24393,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.c linux-2.6.31/fs/aufs/wkq.c
 +              kobject_get(&au_sbi(sb)->si_kobj);
 +              __module_get(THIS_MODULE);
 +
-+              au_wkq_run(wkinfo);
++              au_wkq_run(wkinfo, !AuWkq_WAIT);
 +      } else {
 +              err = -ENOMEM;
 +              atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
@@ -23291,59 +24407,26 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.c linux-2.6.31/fs/aufs/wkq.c
 +void au_nwt_init(struct au_nowait_tasks *nwt)
 +{
 +      atomic_set(&nwt->nw_len, 0);
-+      /* smp_mb();*/ /* atomic_set */
++      /* smp_mb(); */ /* atomic_set */
 +      init_waitqueue_head(&nwt->nw_wq);
 +}
 +
 +void au_wkq_fin(void)
 +{
-+      int i;
-+
-+      for (i = 0; i < aufs_nwkq; i++)
-+              if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
-+                      destroy_workqueue(au_wkq[i].q);
-+      kfree(au_wkq);
++      destroy_workqueue(au_wkq);
 +}
 +
 +int __init au_wkq_init(void)
 +{
-+      int err, i;
-+      struct au_wkq *nowaitq;
-+
-+      /* '+1' is for accounting of nowait queue */
-+      err = -ENOMEM;
-+      au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
-+      if (unlikely(!au_wkq))
-+              goto out;
-+
-+      err = 0;
-+      for (i = 0; i < aufs_nwkq; i++) {
-+              au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
-+              if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
-+                      atomic_set(&au_wkq[i].busy, 0);
-+                      continue;
-+              }
-+
-+              err = PTR_ERR(au_wkq[i].q);
-+              au_wkq_fin();
-+              goto out;
-+      }
-+
-+      /* nowait accounting */
-+      nowaitq = au_wkq + aufs_nwkq;
-+      atomic_set(&nowaitq->busy, 0);
-+      nowaitq->q = NULL;
-+      /* smp_mb(); */ /* atomic_set */
-+
-+ out:
-+      return err;
++      au_wkq = create_workqueue(AUFS_WKQ_NAME);
++      return 0;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.h linux-2.6.31/fs/aufs/wkq.h
---- linux-2.6.31-vanilla/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/wkq.h 2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,82 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/wkq.h linux-2.6.33.1/fs/aufs/wkq.h
+--- linux-2.6.33.1-vanilla/fs/aufs/wkq.h       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/wkq.h       2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,84 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -23407,7 +24490,9 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.h linux-2.6.31/fs/aufs/wkq.h
 +
 +static inline int au_test_wkq(struct task_struct *tsk)
 +{
-+      return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
++      return !tsk->mm
++              && !strncmp(tsk->comm, AUFS_WKQ_NAME "/",
++                          sizeof(AUFS_WKQ_NAME));
 +}
 +
 +static inline void au_nwt_done(struct au_nowait_tasks *nwt)
@@ -23424,12 +24509,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/wkq.h linux-2.6.31/fs/aufs/wkq.h
 +
 +#endif /* __KERNEL__ */
 +#endif /* __AUFS_WKQ_H__ */
-diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
---- linux-2.6.31-vanilla/fs/aufs/xino.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/fs/aufs/xino.c        2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,1203 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/aufs/xino.c linux-2.6.33.1/fs/aufs/xino.c
+--- linux-2.6.33.1-vanilla/fs/aufs/xino.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/fs/aufs/xino.c      2010-04-05 16:53:27.000000000 +0200
+@@ -0,0 +1,1202 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -23487,12 +24572,12 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +
 +      oldfs = get_fs();
 +      set_fs(KERNEL_DS);
-+      lockdep_off();
++      /* lockdep_off(); */
 +      do {
 +              /* todo: signal_pending? */
 +              err = func(file, (const char __user *)buf, size, pos);
 +      } while (err == -EAGAIN || err == -EINTR);
-+      lockdep_on();
++      /* lockdep_on(); */
 +      set_fs(oldfs);
 +
 +#if 0 /* reserved for future use */
@@ -23557,11 +24642,11 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
 +{
 +      struct file *file;
-+      struct dentry *base, *dentry, *parent;
++      struct dentry *base, *parent;
 +      struct inode *dir;
 +      struct qstr *name;
-+      int err;
 +      struct path path;
++      int err;
 +
 +      base = base_file->f_dentry;
 +      parent = base->d_parent; /* dir inode is locked */
@@ -23570,34 +24655,33 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +
 +      file = ERR_PTR(-EINVAL);
 +      name = &base->d_name;
-+      dentry = vfsub_lookup_one_len(name->name, parent, name->len);
-+      if (IS_ERR(dentry)) {
-+              file = (void *)dentry;
-+              AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
++      path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
++      if (IS_ERR(path.dentry)) {
++              file = (void *)path.dentry;
++              pr_err("%.*s lookup err %ld\n",
++                     AuLNPair(name), PTR_ERR(path.dentry));
 +              goto out;
 +      }
 +
 +      /* no need to mnt_want_write() since we call dentry_open() later */
-+      err = vfs_create(dir, dentry, S_IRUGO | S_IWUGO, NULL);
++      err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
 +      if (unlikely(err)) {
 +              file = ERR_PTR(err);
-+              AuErr("%.*s create err %d\n", AuLNPair(name), err);
++              pr_err("%.*s create err %d\n", AuLNPair(name), err);
 +              goto out_dput;
 +      }
 +
-+      path.dentry = dentry;
 +      path.mnt = base_file->f_vfsmnt;
-+      path_get(&path);
-+      file = vfsub_dentry_open(&path, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
-+                               current_cred());
++      file = vfsub_dentry_open(&path,
++                               O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
 +      if (IS_ERR(file)) {
-+              AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
++              pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
 +              goto out_dput;
 +      }
 +
 +      err = vfsub_unlink(dir, &file->f_path, /*force*/0);
 +      if (unlikely(err)) {
-+              AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
++              pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
 +              goto out_fput;
 +      }
 +
@@ -23606,7 +24690,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +              err = au_copy_file(file, copy_src,
 +                                 i_size_read(copy_src->f_dentry->d_inode));
 +              if (unlikely(err)) {
-+                      AuErr("%.*s copy err %d\n", AuLNPair(name), err);
++                      pr_err("%.*s copy err %d\n", AuLNPair(name), err);
 +                      goto out_fput;
 +              }
 +      }
@@ -23616,7 +24700,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +      fput(file);
 +      file = ERR_PTR(err);
 + out_dput:
-+      dput(dentry);
++      dput(path.dentry);
 + out:
 +      return file;
 +}
@@ -23639,7 +24723,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +              bindex = au_br_index(sb, brid);
 +      if (bindex >= 0) {
 +              ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
-+              au_hin_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
++              au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
 +      } else {
 +              ldir->parent = dget_parent(xino->f_dentry);
 +              ldir->mtx = &ldir->parent->d_inode->i_mutex;
@@ -23650,7 +24734,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
 +{
 +      if (ldir->hdir)
-+              au_hin_imtx_unlock(ldir->hdir);
++              au_hn_imtx_unlock(ldir->hdir);
 +      else {
 +              mutex_unlock(ldir->mtx);
 +              dput(ldir->parent);
@@ -23737,7 +24821,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +
 +      ii_read_unlock(dir);
 +      if (unlikely(err))
-+              AuWarn("err b%d, (%d)\n", bindex, err);
++              pr_warning("err b%d, (%d)\n", bindex, err);
 +      atomic_dec(&br->br_xino_running);
 +      atomic_dec(&br->br_count);
 +      au_nwt_done(&au_sbi(sb)->si_nowait);
@@ -23771,7 +24855,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +      if (!wkq_err)
 +              return; /* success */
 +
-+      AuErr("wkq %d\n", wkq_err);
++      pr_err("wkq %d\n", wkq_err);
 +      atomic_dec_return(&br->br_count);
 +
 + out_args:
@@ -24052,14 +25136,14 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +
 +      /*
 +       * at mount-time, and the xino file is the default path,
-+       * hinotify is disabled so we have no inotify events to ignore.
++       * hnotify is disabled so we have no notify events to ignore.
 +       * when a user specified the xino, we cannot get au_hdir to be ignored.
 +       */
 +      file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
 +                             S_IRUGO | S_IWUGO);
 +      if (IS_ERR(file)) {
 +              if (!silent)
-+                      AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
++                      pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
 +              return file;
 +      }
 +
@@ -24073,7 +25157,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +      dput(h_parent);
 +      if (unlikely(err)) {
 +              if (!silent)
-+                      AuErr("unlink %s(%d)\n", fname, err);
++                      pr_err("unlink %s(%d)\n", fname, err);
 +              goto out;
 +      }
 +
@@ -24081,13 +25165,13 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +      d = file->f_dentry;
 +      if (unlikely(sb == d->d_sb)) {
 +              if (!silent)
-+                      AuErr("%s must be outside\n", fname);
++                      pr_err("%s must be outside\n", fname);
 +              goto out;
 +      }
 +      if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
 +              if (!silent)
-+                      AuErr("xino doesn't support %s(%s)\n",
-+                            fname, au_sbtype(d->d_sb));
++                      pr_err("xino doesn't support %s(%s)\n",
++                             fname, au_sbtype(d->d_sb));
 +              goto out;
 +      }
 +      return file; /* success */
@@ -24577,7 +25661,7 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +
 +      if (bwr >= 0) {
 +              file = ERR_PTR(-ENOMEM);
-+              page = __getname();
++              page = __getname_gfp(GFP_NOFS);
 +              if (unlikely(!page))
 +                      goto out;
 +              path.mnt = br->br_mnt;
@@ -24598,8 +25682,8 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 +                      goto out;
 +              h_sb = file->f_dentry->d_sb;
 +              if (unlikely(au_test_fs_bad_xino(h_sb))) {
-+                      AuErr("xino doesn't support %s(%s)\n",
-+                            AUFS_XINO_DEFPATH, au_sbtype(h_sb));
++                      pr_err("xino doesn't support %s(%s)\n",
++                             AUFS_XINO_DEFPATH, au_sbtype(h_sb));
 +                      fput(file);
 +                      file = ERR_PTR(-EINVAL);
 +              }
@@ -24631,29 +25715,29 @@ diff -Nur linux-2.6.31-vanilla/fs/aufs/xino.c linux-2.6.31/fs/aufs/xino.c
 + out:
 +      return err;
 +}
-diff -Nur linux-2.6.31-vanilla/fs/Kconfig linux-2.6.31/fs/Kconfig
---- linux-2.6.31-vanilla/fs/Kconfig    2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/fs/Kconfig    2009-09-16 13:55:56.000000000 +0200
-@@ -187,6 +187,7 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/Kconfig linux-2.6.33.1/fs/Kconfig
+--- linux-2.6.33.1-vanilla/fs/Kconfig  2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/Kconfig  2010-04-05 16:54:40.000000000 +0200
+@@ -188,6 +188,7 @@
+ source "fs/sysv/Kconfig"
  source "fs/ufs/Kconfig"
  source "fs/exofs/Kconfig"
- source "fs/nilfs2/Kconfig"
 +source "fs/aufs/Kconfig"
  
  endif # MISC_FILESYSTEMS
  
-diff -Nur linux-2.6.31-vanilla/fs/Makefile linux-2.6.31/fs/Makefile
---- linux-2.6.31-vanilla/fs/Makefile   2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/fs/Makefile   2009-09-16 13:55:56.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/Makefile linux-2.6.33.1/fs/Makefile
+--- linux-2.6.33.1-vanilla/fs/Makefile 2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/Makefile 2010-04-05 16:54:40.000000000 +0200
 @@ -124,3 +124,4 @@
  obj-$(CONFIG_BTRFS_FS)                += btrfs/
  obj-$(CONFIG_GFS2_FS)           += gfs2/
  obj-$(CONFIG_EXOFS_FS)          += exofs/
 +obj-$(CONFIG_AUFS_FS)           += aufs/
-diff -Nur linux-2.6.31-vanilla/fs/namei.c linux-2.6.31/fs/namei.c
---- linux-2.6.31-vanilla/fs/namei.c    2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/fs/namei.c    2009-09-16 13:55:49.000000000 +0200
-@@ -337,6 +337,7 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/namei.c linux-2.6.33.1/fs/namei.c
+--- linux-2.6.33.1-vanilla/fs/namei.c  2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/namei.c  2010-04-05 16:54:44.000000000 +0200
+@@ -349,6 +349,7 @@
  
        return 0;
  }
@@ -24661,7 +25745,7 @@ diff -Nur linux-2.6.31-vanilla/fs/namei.c linux-2.6.31/fs/namei.c
  
  /**
   * path_get - get a reference to a path
-@@ -1219,7 +1220,7 @@
+@@ -1207,7 +1208,7 @@
   * needs parent already locked. Doesn't follow mounts.
   * SMP-safe.
   */
@@ -24670,7 +25754,7 @@ diff -Nur linux-2.6.31-vanilla/fs/namei.c linux-2.6.31/fs/namei.c
  {
        int err;
  
-@@ -1228,8 +1229,9 @@
+@@ -1216,8 +1217,9 @@
                return ERR_PTR(err);
        return __lookup_hash(&nd->last, nd->path.dentry, nd);
  }
@@ -24681,7 +25765,7 @@ diff -Nur linux-2.6.31-vanilla/fs/namei.c linux-2.6.31/fs/namei.c
                struct dentry *base, int len)
  {
        unsigned long hash;
-@@ -1250,6 +1252,7 @@
+@@ -1238,6 +1240,7 @@
        this->hash = end_name_hash(hash);
        return 0;
  }
@@ -24689,9 +25773,9 @@ diff -Nur linux-2.6.31-vanilla/fs/namei.c linux-2.6.31/fs/namei.c
  
  /**
   * lookup_one_len - filesystem helper to lookup single pathname component
-diff -Nur linux-2.6.31-vanilla/fs/namespace.c linux-2.6.31/fs/namespace.c
---- linux-2.6.31-vanilla/fs/namespace.c        2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/fs/namespace.c        2009-09-16 13:55:49.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/fs/namespace.c linux-2.6.33.1/fs/namespace.c
+--- linux-2.6.33.1-vanilla/fs/namespace.c      2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/namespace.c      2010-04-05 16:54:44.000000000 +0200
 @@ -39,6 +39,7 @@
  
  /* spinlock for vfsmount related operations, inplace of dcache_lock */
@@ -24700,21 +25784,88 @@ diff -Nur linux-2.6.31-vanilla/fs/namespace.c linux-2.6.31/fs/namespace.c
  
  static int event;
  static DEFINE_IDA(mnt_id_ida);
-diff -Nur linux-2.6.31-vanilla/fs/open.c linux-2.6.31/fs/open.c
---- linux-2.6.31-vanilla/fs/open.c     2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/fs/open.c     2009-09-16 13:55:49.000000000 +0200
-@@ -221,6 +221,7 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/notify/group.c linux-2.6.33.1/fs/notify/group.c
+--- linux-2.6.33.1-vanilla/fs/notify/group.c   2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/notify/group.c   2010-04-05 16:54:44.000000000 +0200
+@@ -22,6 +22,7 @@
+ #include <linux/srcu.h>
+ #include <linux/rculist.h>
+ #include <linux/wait.h>
++#include <linux/module.h>
+ #include <linux/fsnotify_backend.h>
+ #include "fsnotify.h"
+@@ -169,6 +170,7 @@
+       fsnotify_recalc_global_mask();
+       fsnotify_destroy_group(group);
+ }
++EXPORT_SYMBOL(fsnotify_put_group);
+ /*
+  * Simply run the fsnotify_groups list and find a group which matches
+@@ -252,3 +254,4 @@
+       return group;
+ }
++EXPORT_SYMBOL(fsnotify_obtain_group);
+diff -Nur linux-2.6.33.1-vanilla/fs/notify/inode_mark.c linux-2.6.33.1/fs/notify/inode_mark.c
+--- linux-2.6.33.1-vanilla/fs/notify/inode_mark.c      2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/notify/inode_mark.c      2010-04-05 16:54:44.000000000 +0200
+@@ -106,6 +106,7 @@
+       if (atomic_dec_and_test(&entry->refcnt))
+               entry->free_mark(entry);
+ }
++EXPORT_SYMBOL(fsnotify_put_mark);
+ /*
+  * Recalculate the mask of events relevant to a given inode locked.
+@@ -216,6 +217,7 @@
+       if (unlikely(atomic_dec_and_test(&group->num_marks)))
+               fsnotify_final_destroy_group(group);
+ }
++EXPORT_SYMBOL(fsnotify_destroy_mark_by_entry);
+ /*
+  * Given a group, destroy all of the marks associated with that group.
+@@ -282,6 +284,7 @@
+       }
+       return NULL;
+ }
++EXPORT_SYMBOL(fsnotify_find_mark_entry);
+ /*
+  * Nothing fancy, just initialize lists and locks and counters.
+@@ -298,6 +301,7 @@
+       entry->inode = NULL;
+       entry->free_mark = free_mark;
+ }
++EXPORT_SYMBOL(fsnotify_init_mark);
+ /*
+  * Attach an initialized mark entry to a given group and inode.
+@@ -353,6 +357,7 @@
+       return ret;
+ }
++EXPORT_SYMBOL(fsnotify_add_mark);
+ /**
+  * fsnotify_unmount_inodes - an sb is unmounting.  handle any watched inodes.
+diff -Nur linux-2.6.33.1-vanilla/fs/open.c linux-2.6.33.1/fs/open.c
+--- linux-2.6.33.1-vanilla/fs/open.c   2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/open.c   2010-04-05 16:54:44.000000000 +0200
+@@ -226,6 +226,7 @@
        mutex_unlock(&dentry->d_inode->i_mutex);
-       return err;
+       return ret;
  }
 +EXPORT_SYMBOL(do_truncate);
  
  static long do_sys_truncate(const char __user *pathname, loff_t length)
  {
-diff -Nur linux-2.6.31-vanilla/fs/splice.c linux-2.6.31/fs/splice.c
---- linux-2.6.31-vanilla/fs/splice.c   2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/fs/splice.c   2009-09-16 13:55:49.000000000 +0200
-@@ -1057,8 +1057,8 @@
+diff -Nur linux-2.6.33.1-vanilla/fs/splice.c linux-2.6.33.1/fs/splice.c
+--- linux-2.6.33.1-vanilla/fs/splice.c 2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/fs/splice.c 2010-04-05 16:54:44.000000000 +0200
+@@ -1053,8 +1053,8 @@
  /*
   * Attempt to initiate a splice from pipe to file.
   */
@@ -24725,7 +25876,7 @@ diff -Nur linux-2.6.31-vanilla/fs/splice.c linux-2.6.31/fs/splice.c
  {
        ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
                                loff_t *, size_t, unsigned int);
-@@ -1080,13 +1080,14 @@
+@@ -1077,13 +1077,14 @@
  
        return splice_write(pipe, out, ppos, len, flags);
  }
@@ -24743,7 +25894,7 @@ diff -Nur linux-2.6.31-vanilla/fs/splice.c linux-2.6.31/fs/splice.c
  {
        ssize_t (*splice_read)(struct file *, loff_t *,
                               struct pipe_inode_info *, size_t, unsigned int);
-@@ -1105,6 +1106,7 @@
+@@ -1103,6 +1104,7 @@
  
        return splice_read(in, ppos, pipe, len, flags);
  }
@@ -24751,12 +25902,12 @@ diff -Nur linux-2.6.31-vanilla/fs/splice.c linux-2.6.31/fs/splice.c
  
  /**
   * splice_direct_to_actor - splices data directly between two non-pipes
-diff -Nur linux-2.6.31-vanilla/include/linux/aufs_type.h linux-2.6.31/include/linux/aufs_type.h
---- linux-2.6.31-vanilla/include/linux/aufs_type.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/include/linux/aufs_type.h     2009-09-16 13:55:30.000000000 +0200
-@@ -0,0 +1,184 @@
+diff -Nur linux-2.6.33.1-vanilla/include/linux/aufs_type.h linux-2.6.33.1/include/linux/aufs_type.h
+--- linux-2.6.33.1-vanilla/include/linux/aufs_type.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.33.1/include/linux/aufs_type.h   2010-04-05 16:53:31.000000000 +0200
+@@ -0,0 +1,198 @@
 +/*
-+ * Copyright (C) 2005-2009 Junjiro R. Okajima
++ * Copyright (C) 2005-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
@@ -24777,9 +25928,14 @@ diff -Nur linux-2.6.31-vanilla/include/linux/aufs_type.h linux-2.6.31/include/li
 +#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-20090914"
++#define AUFS_VERSION  "2-standalone.tree-33-20100405"
 +
 +/* todo? move this to linux-2.6.19/include/magic.h */
 +#define AUFS_SUPER_MAGIC      ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -24816,6 +25972,12 @@ diff -Nur linux-2.6.31-vanilla/include/linux/aufs_type.h linux-2.6.31/include/li
 +
 +#define AUFS_WH_PFX           ".wh."
 +#define AUFS_WH_PFX_LEN               ((int)sizeof(AUFS_WH_PFX) - 1)
++#define AUFS_WH_TMP_LEN               4
++/* a limit for rmdir/rename a dir */
++#define AUFS_MAX_NAMELEN      (NAME_MAX \
++                              - AUFS_WH_PFX_LEN * 2   /* doubly whiteouted */\
++                              - 1                     /* dot */\
++                              - AUFS_WH_TMP_LEN)      /* hex */
 +#define AUFS_XINO_FNAME               "." AUFS_NAME ".xino"
 +#define AUFS_XINO_DEFPATH     "/tmp/" AUFS_XINO_FNAME
 +#define AUFS_XINO_TRUNC_INIT  64 /* blocks */
@@ -24825,7 +25987,6 @@ diff -Nur linux-2.6.31-vanilla/include/linux/aufs_type.h linux-2.6.31/include/li
 +#define AUFS_RDBLK_DEF                512 /* bytes */
 +#define AUFS_RDHASH_DEF               32
 +#define AUFS_WKQ_NAME         AUFS_NAME "d"
-+#define AUFS_NWKQ_DEF         4
 +#define AUFS_MFS_SECOND_DEF   30 /* seconds */
 +#define AUFS_PLINK_WARN               100 /* number of plinks */
 +
@@ -24860,7 +26021,10 @@ diff -Nur linux-2.6.31-vanilla/include/linux/aufs_type.h linux-2.6.31/include/li
 +
 +      /* readdir in userspace */
 +      AuCtl_RDU,
-+      AuCtl_RDU_INO
++      AuCtl_RDU_INO,
++
++      /* pathconf wrapper */
++      AuCtl_WBR_FD
 +};
 +
 +/* borrowed from linux/include/linux/kernel.h */
@@ -24937,11 +26101,12 @@ diff -Nur linux-2.6.31-vanilla/include/linux/aufs_type.h linux-2.6.31/include/li
 +#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)
 +
 +#endif /* __AUFS_TYPE_H__ */
-diff -Nur linux-2.6.31-vanilla/include/linux/Kbuild linux-2.6.31/include/linux/Kbuild
---- linux-2.6.31-vanilla/include/linux/Kbuild  2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/include/linux/Kbuild  2009-09-16 13:55:56.000000000 +0200
+diff -Nur linux-2.6.33.1-vanilla/include/linux/Kbuild linux-2.6.33.1/include/linux/Kbuild
+--- linux-2.6.33.1-vanilla/include/linux/Kbuild        2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/include/linux/Kbuild        2010-04-05 16:54:40.000000000 +0200
 @@ -34,6 +34,7 @@
  header-y += atmsap.h
  header-y += atmsvc.h
@@ -24950,22 +26115,22 @@ diff -Nur linux-2.6.31-vanilla/include/linux/Kbuild linux-2.6.31/include/linux/K
  header-y += auto_fs4.h
  header-y += ax25.h
  header-y += b1lli.h
-diff -Nur linux-2.6.31-vanilla/include/linux/namei.h linux-2.6.31/include/linux/namei.h
---- linux-2.6.31-vanilla/include/linux/namei.h 2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/include/linux/namei.h 2009-09-16 13:55:46.000000000 +0200
-@@ -75,6 +75,9 @@
- extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
extern void release_open_intent(struct nameidata *);
+diff -Nur linux-2.6.33.1-vanilla/include/linux/namei.h linux-2.6.33.1/include/linux/namei.h
+--- linux-2.6.33.1-vanilla/include/linux/namei.h       2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/include/linux/namei.h       2010-04-05 16:54:34.000000000 +0200
+@@ -73,6 +73,9 @@
+ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
              int (*open)(struct inode *, struct file *));
  
 +extern struct dentry *lookup_hash(struct nameidata *nd);
 +extern int __lookup_one_len(const char *name, struct qstr *this,
 +                          struct dentry *base, int len);
  extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
- extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
  
-diff -Nur linux-2.6.31-vanilla/include/linux/splice.h linux-2.6.31/include/linux/splice.h
---- linux-2.6.31-vanilla/include/linux/splice.h        2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/include/linux/splice.h        2009-09-16 13:55:46.000000000 +0200
+ extern int follow_down(struct path *);
+diff -Nur linux-2.6.33.1-vanilla/include/linux/splice.h linux-2.6.33.1/include/linux/splice.h
+--- linux-2.6.33.1-vanilla/include/linux/splice.h      2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/include/linux/splice.h      2010-04-05 16:54:34.000000000 +0200
 @@ -82,4 +82,10 @@
  extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
                                      splice_direct_actor *);
@@ -24977,10 +26142,18 @@ diff -Nur linux-2.6.31-vanilla/include/linux/splice.h linux-2.6.31/include/linux
 +                       unsigned int flags);
 +
  #endif
-diff -Nur linux-2.6.31-vanilla/security/device_cgroup.c linux-2.6.31/security/device_cgroup.c
---- linux-2.6.31-vanilla/security/device_cgroup.c      2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/security/device_cgroup.c      2009-09-16 13:55:49.000000000 +0200
-@@ -513,6 +513,7 @@
+diff -Nur linux-2.6.33.1-vanilla/security/commoncap.c linux-2.6.33.1/security/commoncap.c
+--- linux-2.6.33.1-vanilla/security/commoncap.c        2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/security/commoncap.c        2010-04-05 16:54:44.000000000 +0200
+@@ -946,3 +946,4 @@
+       }
+       return ret;
+ }
++EXPORT_SYMBOL(cap_file_mmap);
+diff -Nur linux-2.6.33.1-vanilla/security/device_cgroup.c linux-2.6.33.1/security/device_cgroup.c
+--- linux-2.6.33.1-vanilla/security/device_cgroup.c    2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/security/device_cgroup.c    2010-04-05 16:54:44.000000000 +0200
+@@ -514,6 +514,7 @@
  
        return -EPERM;
  }
@@ -24988,393 +26161,10 @@ diff -Nur linux-2.6.31-vanilla/security/device_cgroup.c linux-2.6.31/security/de
  
  int devcgroup_inode_mknod(int mode, dev_t dev)
  {
-diff -Nur linux-2.6.31-vanilla/security/integrity/ima/ima_main.c linux-2.6.31/security/integrity/ima/ima_main.c
---- linux-2.6.31-vanilla/security/integrity/ima/ima_main.c     2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/security/integrity/ima/ima_main.c     2009-09-16 13:55:49.000000000 +0200
-@@ -324,6 +324,7 @@
-                                        MAY_EXEC, FILE_MMAP);
-       return 0;
- }
-+EXPORT_SYMBOL(ima_file_mmap);
- /**
-  * ima_bprm_check - based on policy, collect/store measurement.
-diff -Nur linux-2.6.31-vanilla/security/integrity/ima/ima_main.c.orig linux-2.6.31/security/integrity/ima/ima_main.c.orig
---- linux-2.6.31-vanilla/security/integrity/ima/ima_main.c.orig        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.31/security/integrity/ima/ima_main.c.orig        2009-09-10 00:13:59.000000000 +0200
-@@ -0,0 +1,368 @@
-+/*
-+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
-+ *
-+ * Authors:
-+ * Reiner Sailer <sailer@watson.ibm.com>
-+ * Serge Hallyn <serue@us.ibm.com>
-+ * Kylene Hall <kylene@us.ibm.com>
-+ * Mimi Zohar <zohar@us.ibm.com>
-+ *
-+ * This program 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, version 2 of the
-+ * License.
-+ *
-+ * File: ima_main.c
-+ *             implements the IMA hooks: ima_bprm_check, ima_file_mmap,
-+ *             and ima_path_check.
-+ */
-+#include <linux/module.h>
-+#include <linux/file.h>
-+#include <linux/binfmts.h>
-+#include <linux/mount.h>
-+#include <linux/mman.h>
-+
-+#include "ima.h"
-+
-+int ima_initialized;
-+
-+char *ima_hash = "sha1";
-+static int __init hash_setup(char *str)
-+{
-+      if (strncmp(str, "md5", 3) == 0)
-+              ima_hash = "md5";
-+      return 1;
-+}
-+__setup("ima_hash=", hash_setup);
-+
-+/**
-+ * ima_file_free - called on __fput()
-+ * @file: pointer to file structure being freed
-+ *
-+ * Flag files that changed, based on i_version;
-+ * and decrement the iint readcount/writecount.
-+ */
-+void ima_file_free(struct file *file)
-+{
-+      struct inode *inode = file->f_dentry->d_inode;
-+      struct ima_iint_cache *iint;
-+
-+      if (!ima_initialized || !S_ISREG(inode->i_mode))
-+              return;
-+      iint = ima_iint_find_get(inode);
-+      if (!iint)
-+              return;
-+
-+      mutex_lock(&iint->mutex);
-+      if (iint->opencount <= 0) {
-+              printk(KERN_INFO
-+                     "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n",
-+                     __FUNCTION__, file->f_dentry->d_name.name,
-+                     iint->readcount, iint->writecount,
-+                     iint->opencount, atomic_long_read(&file->f_count));
-+              if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
-+                      dump_stack();
-+                      iint->flags |= IMA_IINT_DUMP_STACK;
-+              }
-+      }
-+      iint->opencount--;
-+
-+      if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-+              iint->readcount--;
-+
-+      if (file->f_mode & FMODE_WRITE) {
-+              iint->writecount--;
-+              if (iint->writecount == 0) {
-+                      if (iint->version != inode->i_version)
-+                              iint->flags &= ~IMA_MEASURED;
-+              }
-+      }
-+      mutex_unlock(&iint->mutex);
-+      kref_put(&iint->refcount, iint_free);
-+}
-+
-+/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
-+ *
-+ * When opening a file for read, if the file is already open for write,
-+ * the file could change, resulting in a file measurement error.
-+ *
-+ * Opening a file for write, if the file is already open for read, results
-+ * in a time of measure, time of use (ToMToU) error.
-+ *
-+ * In either case invalidate the PCR.
-+ */
-+enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
-+static void ima_read_write_check(enum iint_pcr_error error,
-+                               struct ima_iint_cache *iint,
-+                               struct inode *inode,
-+                               const unsigned char *filename)
-+{
-+      switch (error) {
-+      case TOMTOU:
-+              if (iint->readcount > 0)
-+                      ima_add_violation(inode, filename, "invalid_pcr",
-+                                        "ToMToU");
-+              break;
-+      case OPEN_WRITERS:
-+              if (iint->writecount > 0)
-+                      ima_add_violation(inode, filename, "invalid_pcr",
-+                                        "open_writers");
-+              break;
-+      }
-+}
-+
-+static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
-+                              const unsigned char *filename)
-+{
-+      int rc = 0;
-+
-+      iint->opencount++;
-+      iint->readcount++;
-+
-+      rc = ima_collect_measurement(iint, file);
-+      if (!rc)
-+              ima_store_measurement(iint, file, filename);
-+      return rc;
-+}
-+
-+static void ima_update_counts(struct ima_iint_cache *iint, int mask)
-+{
-+      iint->opencount++;
-+      if ((mask & MAY_WRITE) || (mask == 0))
-+              iint->writecount++;
-+      else if (mask & (MAY_READ | MAY_EXEC))
-+              iint->readcount++;
-+}
-+
-+/**
-+ * ima_path_check - based on policy, collect/store measurement.
-+ * @path: contains a pointer to the path to be measured
-+ * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
-+ *
-+ * Measure the file being open for readonly, based on the
-+ * ima_must_measure() policy decision.
-+ *
-+ * Keep read/write counters for all files, but only
-+ * invalidate the PCR for measured files:
-+ *    - Opening a file for write when already open for read,
-+ *      results in a time of measure, time of use (ToMToU) error.
-+ *    - Opening a file for read when already open for write,
-+ *      could result in a file measurement error.
-+ *
-+ * Always return 0 and audit dentry_open failures.
-+ * (Return code will be based upon measurement appraisal.)
-+ */
-+int ima_path_check(struct path *path, int mask, int update_counts)
-+{
-+      struct inode *inode = path->dentry->d_inode;
-+      struct ima_iint_cache *iint;
-+      struct file *file = NULL;
-+      int rc;
-+
-+      if (!ima_initialized || !S_ISREG(inode->i_mode))
-+              return 0;
-+      iint = ima_iint_find_insert_get(inode);
-+      if (!iint)
-+              return 0;
-+
-+      mutex_lock(&iint->mutex);
-+      if (update_counts)
-+              ima_update_counts(iint, mask);
-+
-+      rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
-+      if (rc < 0)
-+              goto out;
-+
-+      if ((mask & MAY_WRITE) || (mask == 0))
-+              ima_read_write_check(TOMTOU, iint, inode,
-+                                   path->dentry->d_name.name);
-+
-+      if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
-+              goto out;
-+
-+      ima_read_write_check(OPEN_WRITERS, iint, inode,
-+                           path->dentry->d_name.name);
-+      if (!(iint->flags & IMA_MEASURED)) {
-+              struct dentry *dentry = dget(path->dentry);
-+              struct vfsmount *mnt = mntget(path->mnt);
-+
-+              file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE,
-+                                 current_cred());
-+              if (IS_ERR(file)) {
-+                      int audit_info = 0;
-+
-+                      integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
-+                                          dentry->d_name.name,
-+                                          "add_measurement",
-+                                          "dentry_open failed",
-+                                          1, audit_info);
-+                      file = NULL;
-+                      goto out;
-+              }
-+              rc = get_path_measurement(iint, file, dentry->d_name.name);
-+      }
-+out:
-+      mutex_unlock(&iint->mutex);
-+      if (file)
-+              fput(file);
-+      kref_put(&iint->refcount, iint_free);
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ima_path_check);
-+
-+static int process_measurement(struct file *file, const unsigned char *filename,
-+                             int mask, int function)
-+{
-+      struct inode *inode = file->f_dentry->d_inode;
-+      struct ima_iint_cache *iint;
-+      int rc;
-+
-+      if (!ima_initialized || !S_ISREG(inode->i_mode))
-+              return 0;
-+      iint = ima_iint_find_insert_get(inode);
-+      if (!iint)
-+              return -ENOMEM;
-+
-+      mutex_lock(&iint->mutex);
-+      rc = ima_must_measure(iint, inode, mask, function);
-+      if (rc != 0)
-+              goto out;
-+
-+      rc = ima_collect_measurement(iint, file);
-+      if (!rc)
-+              ima_store_measurement(iint, file, filename);
-+out:
-+      mutex_unlock(&iint->mutex);
-+      kref_put(&iint->refcount, iint_free);
-+      return rc;
-+}
-+
-+/*
-+ * ima_counts_put - decrement file counts
-+ *
-+ * File counts are incremented in ima_path_check. On file open
-+ * error, such as ETXTBSY, decrement the counts to prevent
-+ * unnecessary imbalance messages.
-+ */
-+void ima_counts_put(struct path *path, int mask)
-+{
-+      struct inode *inode = path->dentry->d_inode;
-+      struct ima_iint_cache *iint;
-+
-+      /* The inode may already have been freed, freeing the iint
-+       * with it. Verify the inode is not NULL before dereferencing
-+       * it.
-+       */
-+      if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
-+              return;
-+      iint = ima_iint_find_insert_get(inode);
-+      if (!iint)
-+              return;
-+
-+      mutex_lock(&iint->mutex);
-+      iint->opencount--;
-+      if ((mask & MAY_WRITE) || (mask == 0))
-+              iint->writecount--;
-+      else if (mask & (MAY_READ | MAY_EXEC))
-+              iint->readcount--;
-+      mutex_unlock(&iint->mutex);
-+
-+      kref_put(&iint->refcount, iint_free);
-+}
-+
-+/*
-+ * ima_counts_get - increment file counts
-+ *
-+ * - for IPC shm and shmat file.
-+ * - for nfsd exported files.
-+ *
-+ * Increment the counts for these files to prevent unnecessary
-+ * imbalance messages.
-+ */
-+void ima_counts_get(struct file *file)
-+{
-+      struct inode *inode = file->f_dentry->d_inode;
-+      struct ima_iint_cache *iint;
-+
-+      if (!ima_initialized || !S_ISREG(inode->i_mode))
-+              return;
-+      iint = ima_iint_find_insert_get(inode);
-+      if (!iint)
-+              return;
-+      mutex_lock(&iint->mutex);
-+      iint->opencount++;
-+      if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-+              iint->readcount++;
-+
-+      if (file->f_mode & FMODE_WRITE)
-+              iint->writecount++;
-+      mutex_unlock(&iint->mutex);
-+
-+      kref_put(&iint->refcount, iint_free);
-+}
-+EXPORT_SYMBOL_GPL(ima_counts_get);
-+
-+/**
-+ * ima_file_mmap - based on policy, collect/store measurement.
-+ * @file: pointer to the file to be measured (May be NULL)
-+ * @prot: contains the protection that will be applied by the kernel.
-+ *
-+ * Measure files being mmapped executable based on the ima_must_measure()
-+ * policy decision.
-+ *
-+ * Return 0 on success, an error code on failure.
-+ * (Based on the results of appraise_measurement().)
-+ */
-+int ima_file_mmap(struct file *file, unsigned long prot)
-+{
-+      int rc;
-+
-+      if (!file)
-+              return 0;
-+      if (prot & PROT_EXEC)
-+              rc = process_measurement(file, file->f_dentry->d_name.name,
-+                                       MAY_EXEC, FILE_MMAP);
-+      return 0;
-+}
-+
-+/**
-+ * ima_bprm_check - based on policy, collect/store measurement.
-+ * @bprm: contains the linux_binprm structure
-+ *
-+ * The OS protects against an executable file, already open for write,
-+ * from being executed in deny_write_access() and an executable file,
-+ * already open for execute, from being modified in get_write_access().
-+ * So we can be certain that what we verify and measure here is actually
-+ * what is being executed.
-+ *
-+ * Return 0 on success, an error code on failure.
-+ * (Based on the results of appraise_measurement().)
-+ */
-+int ima_bprm_check(struct linux_binprm *bprm)
-+{
-+      int rc;
-+
-+      rc = process_measurement(bprm->file, bprm->filename,
-+                               MAY_EXEC, BPRM_CHECK);
-+      return 0;
-+}
-+
-+static int __init init_ima(void)
-+{
-+      int error;
-+
-+      ima_iintcache_init();
-+      error = ima_init();
-+      ima_initialized = 1;
-+      return error;
-+}
-+
-+static void __exit cleanup_ima(void)
-+{
-+      ima_cleanup();
-+}
-+
-+late_initcall(init_ima);      /* Start IMA after the TPM is available */
-+
-+MODULE_DESCRIPTION("Integrity Measurement Architecture");
-+MODULE_LICENSE("GPL");
-diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/security.c
---- linux-2.6.31-vanilla/security/security.c   2009-09-10 00:13:59.000000000 +0200
-+++ linux-2.6.31/security/security.c   2009-09-16 13:55:49.000000000 +0200
-@@ -386,6 +386,7 @@
+diff -Nur linux-2.6.33.1-vanilla/security/security.c linux-2.6.33.1/security/security.c
+--- linux-2.6.33.1-vanilla/security/security.c 2010-03-15 17:09:39.000000000 +0100
++++ linux-2.6.33.1/security/security.c 2010-04-05 16:54:44.000000000 +0200
+@@ -404,6 +404,7 @@
                return 0;
        return security_ops->path_mkdir(path, dentry, mode);
  }
@@ -25382,7 +26172,7 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_path_rmdir(struct path *path, struct dentry *dentry)
  {
-@@ -393,6 +394,7 @@
+@@ -411,6 +412,7 @@
                return 0;
        return security_ops->path_rmdir(path, dentry);
  }
@@ -25390,7 +26180,7 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_path_unlink(struct path *path, struct dentry *dentry)
  {
-@@ -400,6 +402,7 @@
+@@ -418,6 +420,7 @@
                return 0;
        return security_ops->path_unlink(path, dentry);
  }
@@ -25398,7 +26188,7 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_path_symlink(struct path *path, struct dentry *dentry,
                          const char *old_name)
-@@ -408,6 +411,7 @@
+@@ -426,6 +429,7 @@
                return 0;
        return security_ops->path_symlink(path, dentry, old_name);
  }
@@ -25406,7 +26196,7 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_path_link(struct dentry *old_dentry, struct path *new_dir,
                       struct dentry *new_dentry)
-@@ -416,6 +420,7 @@
+@@ -434,6 +438,7 @@
                return 0;
        return security_ops->path_link(old_dentry, new_dir, new_dentry);
  }
@@ -25414,7 +26204,7 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
                         struct path *new_dir, struct dentry *new_dentry)
-@@ -426,6 +431,7 @@
+@@ -444,6 +449,7 @@
        return security_ops->path_rename(old_dir, old_dentry, new_dir,
                                         new_dentry);
  }
@@ -25422,15 +26212,31 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_path_truncate(struct path *path, loff_t length,
                           unsigned int time_attrs)
-@@ -434,6 +440,7 @@
+@@ -452,6 +458,7 @@
                return 0;
        return security_ops->path_truncate(path, length, time_attrs);
  }
 +EXPORT_SYMBOL(security_path_truncate);
- #endif
  
- int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
-@@ -505,6 +512,7 @@
+ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+                       mode_t mode)
+@@ -460,6 +467,7 @@
+               return 0;
+       return security_ops->path_chmod(dentry, mnt, mode);
+ }
++EXPORT_SYMBOL(security_path_chmod);
+ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
+ {
+@@ -467,6 +475,7 @@
+               return 0;
+       return security_ops->path_chown(path, uid, gid);
+ }
++EXPORT_SYMBOL(security_path_chown);
+ int security_path_chroot(struct path *path)
+ {
+@@ -543,6 +552,7 @@
                return 0;
        return security_ops->inode_readlink(dentry);
  }
@@ -25438,7 +26244,7 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
  {
-@@ -519,6 +527,7 @@
+@@ -557,6 +567,7 @@
                return 0;
        return security_ops->inode_permission(inode, mask);
  }
@@ -25446,7 +26252,7 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
  {
-@@ -619,6 +628,7 @@
+@@ -657,6 +668,7 @@
  {
        return security_ops->file_permission(file, mask);
  }
@@ -25454,3 +26260,11 @@ diff -Nur linux-2.6.31-vanilla/security/security.c linux-2.6.31/security/securit
  
  int security_file_alloc(struct file *file)
  {
+@@ -684,6 +696,7 @@
+               return ret;
+       return ima_file_mmap(file, prot);
+ }
++EXPORT_SYMBOL(security_file_mmap);
+ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
+                           unsigned long prot)