summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArkadiusz Miƛkiewicz2010-11-22 11:36:06 (GMT)
committercvs2git2012-06-24 12:13:13 (GMT)
commit7f207e10d4050e47df14b442a5bec5c522af38ea (patch)
treecbc238cae38fd5fd074e2421398b68a52b77d9b6
parentc49e75c6a4848ea8ce322cb73c949cb2d47f7852 (diff)
downloadkernel-7f207e10d4050e47df14b442a5bec5c522af38ea.zip
kernel-7f207e10d4050e47df14b442a5bec5c522af38ea.tar.gz
official aufs2.1 patch
Changed files: kernel-aufs2.patch -> 1.15
-rw-r--r--kernel-aufs2.patch2202
1 files changed, 1152 insertions, 1050 deletions
diff --git a/kernel-aufs2.patch b/kernel-aufs2.patch
index bd49a1e..d572cb1 100644
--- a/kernel-aufs2.patch
+++ b/kernel-aufs2.patch
@@ -1,5 +1,411 @@
---- /dev/null
-+++ linux-2.6/Documentation/ABI/testing/debugfs-aufs 2010-10-25 14:20:44.000000000 +0200
+aufs2.1 kbuild patch for linux-2.6.36
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 3d18530..8f582e1 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -189,6 +189,7 @@ source "fs/romfs/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
+ source "fs/exofs/Kconfig"
++source "fs/aufs/Kconfig"
+
+ endif # MISC_FILESYSTEMS
+
+diff --git a/fs/Makefile b/fs/Makefile
+index e6ec1d3..b0d795a 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS) += btrfs/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
+ obj-$(CONFIG_EXOFS_FS) += exofs/
+ obj-$(CONFIG_CEPH_FS) += ceph/
++obj-$(CONFIG_AUFS_FS) += aufs/
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 4e8ea8c..b8fc201 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -60,6 +60,7 @@ header-y += atmppp.h
+ header-y += atmsap.h
+ header-y += atmsvc.h
+ header-y += audit.h
++header-y += aufs_type.h
+ header-y += auto_fs.h
+ header-y += auto_fs4.h
+ header-y += auxvec.h
+aufs2.1 base patch for linux-2.6.36
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 24896e8..19d69c5 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1159,7 +1159,7 @@ out:
+ * needs parent already locked. Doesn't follow mounts.
+ * SMP-safe.
+ */
+-static struct dentry *lookup_hash(struct nameidata *nd)
++struct dentry *lookup_hash(struct nameidata *nd)
+ {
+ int err;
+
+@@ -1169,7 +1169,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
+ return __lookup_hash(&nd->last, nd->path.dentry, nd);
+ }
+
+-static int __lookup_one_len(const char *name, struct qstr *this,
++int __lookup_one_len(const char *name, struct qstr *this,
+ struct dentry *base, int len)
+ {
+ unsigned long hash;
+diff --git a/fs/splice.c b/fs/splice.c
+index 8f1dfae..278c94f 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -1092,8 +1092,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+ * Attempt to initiate a splice from pipe to file.
+ */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+- loff_t *ppos, size_t len, unsigned int flags)
++long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
+ {
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
+ loff_t *, size_t, unsigned int);
+@@ -1120,9 +1120,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ /*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+- struct pipe_inode_info *pipe, size_t len,
+- unsigned int flags)
++long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
+ {
+ ssize_t (*splice_read)(struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, unsigned int);
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index 05b441d..91bc74e 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -73,6 +73,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
+ 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 int follow_down(struct path *);
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 997c3b4..be9a153 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
+ extern void splice_shrink_spd(struct pipe_inode_info *,
+ struct splice_pipe_desc *);
+
++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++extern long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
++
+ #endif
+aufs2.1 standalone patch for linux-2.6.36
+
+diff --git a/fs/file_table.c b/fs/file_table.c
+index a04bdd8..f51588f 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -394,6 +394,8 @@ void file_sb_list_del(struct file *file)
+ }
+ }
+
++EXPORT_SYMBOL(file_sb_list_del);
++
+ #ifdef CONFIG_SMP
+
+ /*
+diff --git a/fs/inode.c b/fs/inode.c
+index 8646433..d84944d 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -83,6 +83,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
+ * the i_state of an inode while it is in use..
+ */
+ DEFINE_SPINLOCK(inode_lock);
++EXPORT_SYMBOL(inode_lock);
+
+ /*
+ * iprune_sem provides exclusion between the kswapd or try_to_free_pages
+diff --git a/fs/namei.c b/fs/namei.c
+index 19d69c5..944842e 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -347,6 +347,7 @@ int deny_write_access(struct file * file)
+
+ return 0;
+ }
++EXPORT_SYMBOL(deny_write_access);
+
+ /**
+ * path_get - get a reference to a path
+@@ -1168,6 +1169,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
+ return ERR_PTR(err);
+ return __lookup_hash(&nd->last, nd->path.dentry, nd);
+ }
++EXPORT_SYMBOL(lookup_hash);
+
+ int __lookup_one_len(const char *name, struct qstr *this,
+ struct dentry *base, int len)
+@@ -1190,6 +1192,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
+ this->hash = end_name_hash(hash);
+ return 0;
+ }
++EXPORT_SYMBOL(__lookup_one_len);
+
+ /**
+ * lookup_one_len - filesystem helper to lookup single pathname component
+diff --git a/fs/namespace.c b/fs/namespace.c
+index a72eaab..36107eb 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -1322,6 +1322,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+ }
+ return 0;
+ }
++EXPORT_SYMBOL(iterate_mounts);
+
+ static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
+ {
+diff --git a/fs/notify/group.c b/fs/notify/group.c
+index d309f38..f0e9568 100644
+--- a/fs/notify/group.c
++++ b/fs/notify/group.c
+@@ -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"
+@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
+ if (atomic_dec_and_test(&group->refcnt))
+ fsnotify_destroy_group(group);
+ }
++EXPORT_SYMBOL(fsnotify_put_group);
+
+ /*
+ * Create a new fsnotify_group and hold a reference for the group returned.
+@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
+
+ return group;
+ }
++EXPORT_SYMBOL(fsnotify_alloc_group);
+diff --git a/fs/notify/mark.c b/fs/notify/mark.c
+index 325185e..adede09 100644
+--- a/fs/notify/mark.c
++++ b/fs/notify/mark.c
+@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
+ if (atomic_dec_and_test(&mark->refcnt))
+ mark->free_mark(mark);
+ }
++EXPORT_SYMBOL(fsnotify_put_mark);
+
+ /*
+ * Any time a mark is getting freed we end up here.
+@@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
+ if (unlikely(atomic_dec_and_test(&group->num_marks)))
+ fsnotify_final_destroy_group(group);
+ }
++EXPORT_SYMBOL(fsnotify_destroy_mark);
+
+ void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
+ {
+@@ -277,6 +279,7 @@ err:
+
+ return ret;
+ }
++EXPORT_SYMBOL(fsnotify_add_mark);
+
+ /*
+ * clear any marks in a group in which mark->flags & flags is true
+@@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
+ atomic_set(&mark->refcnt, 1);
+ mark->free_mark = free_mark;
+ }
++EXPORT_SYMBOL(fsnotify_init_mark);
+
+ static int fsnotify_mark_destroy(void *ignored)
+ {
+diff --git a/fs/open.c b/fs/open.c
+index d74e198..53ef25e 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+ mutex_unlock(&dentry->d_inode->i_mutex);
+ return ret;
+ }
++EXPORT_SYMBOL(do_truncate);
+
+ static long do_sys_truncate(const char __user *pathname, loff_t length)
+ {
+diff --git a/fs/splice.c b/fs/splice.c
+index 278c94f..033f7ac 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -1116,6 +1116,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+
+ return splice_write(pipe, out, ppos, len, flags);
+ }
++EXPORT_SYMBOL(do_splice_from);
+
+ /*
+ * Attempt to initiate a splice from a file to a pipe.
+@@ -1142,6 +1143,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
+
+ return splice_read(in, ppos, pipe, len, flags);
+ }
++EXPORT_SYMBOL(do_splice_to);
+
+ /**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+diff --git a/security/commoncap.c b/security/commoncap.c
+index 9d172e6..8a61084 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
+ }
+ return ret;
+ }
++EXPORT_SYMBOL(cap_file_mmap);
+diff --git a/security/device_cgroup.c b/security/device_cgroup.c
+index 8d9c48f..29108aa 100644
+--- a/security/device_cgroup.c
++++ b/security/device_cgroup.c
+@@ -515,6 +515,7 @@ found:
+
+ return -EPERM;
+ }
++EXPORT_SYMBOL(devcgroup_inode_permission);
+
+ int devcgroup_inode_mknod(int mode, dev_t dev)
+ {
+diff --git a/security/security.c b/security/security.c
+index c53949f..0ae5b91 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
+ return 0;
+ return security_ops->path_mkdir(dir, dentry, mode);
+ }
++EXPORT_SYMBOL(security_path_mkdir);
+
+ int security_path_rmdir(struct path *dir, struct dentry *dentry)
+ {
+@@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
+ return 0;
+ return security_ops->path_rmdir(dir, dentry);
+ }
++EXPORT_SYMBOL(security_path_rmdir);
+
+ int security_path_unlink(struct path *dir, struct dentry *dentry)
+ {
+@@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
+ return 0;
+ return security_ops->path_unlink(dir, dentry);
+ }
++EXPORT_SYMBOL(security_path_unlink);
+
+ int security_path_symlink(struct path *dir, struct dentry *dentry,
+ const char *old_name)
+@@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
+ return 0;
+ return security_ops->path_symlink(dir, dentry, old_name);
+ }
++EXPORT_SYMBOL(security_path_symlink);
+
+ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+ struct dentry *new_dentry)
+@@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+ return 0;
+ return security_ops->path_link(old_dentry, new_dir, new_dentry);
+ }
++EXPORT_SYMBOL(security_path_link);
+
+ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+ struct path *new_dir, struct dentry *new_dentry)
+@@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+ return security_ops->path_rename(old_dir, old_dentry, new_dir,
+ new_dentry);
+ }
++EXPORT_SYMBOL(security_path_rename);
+
+ int security_path_truncate(struct path *path)
+ {
+@@ -423,6 +429,7 @@ int security_path_truncate(struct path *path)
+ return 0;
+ return security_ops->path_truncate(path);
+ }
++EXPORT_SYMBOL(security_path_truncate);
+
+ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+ mode_t mode)
+@@ -431,6 +438,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+ 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)
+ {
+@@ -438,6 +446,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
+ return 0;
+ return security_ops->path_chown(path, uid, gid);
+ }
++EXPORT_SYMBOL(security_path_chown);
+
+ int security_path_chroot(struct path *path)
+ {
+@@ -514,6 +523,7 @@ int security_inode_readlink(struct dentry *dentry)
+ return 0;
+ return security_ops->inode_readlink(dentry);
+ }
++EXPORT_SYMBOL(security_inode_readlink);
+
+ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+@@ -528,6 +538,7 @@ int security_inode_permission(struct inode *inode, int mask)
+ return 0;
+ return security_ops->inode_permission(inode, mask);
+ }
++EXPORT_SYMBOL(security_inode_permission);
+
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
+@@ -627,6 +638,7 @@ int security_file_permission(struct file *file, int mask)
+
+ return fsnotify_perm(file, mask);
+ }
++EXPORT_SYMBOL(security_file_permission);
+
+ int security_file_alloc(struct file *file)
+ {
+@@ -654,6 +666,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
+ 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)
+diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
+--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
++++ linux/Documentation/ABI/testing/debugfs-aufs 2010-11-22 11:52:56.970558852 +0100
@@ -0,0 +1,37 @@
+What: /debug/aufs/si_<id>/
+Date: March 2009
@@ -38,8 +444,9 @@
+ be created.
+ When the aufs mount option 'noxino' is specified, it
+ will be empty. About XINO files, see the aufs manual.
---- /dev/null
-+++ linux-2.6/Documentation/ABI/testing/sysfs-aufs 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
+--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
++++ linux/Documentation/ABI/testing/sysfs-aufs 2010-11-22 11:52:56.970558852 +0100
@@ -0,0 +1,24 @@
+What: /sys/fs/aufs/si_<id>/
+Date: March 2009
@@ -65,8 +472,9 @@
+ even if it is the default path.
+ When the aufs mount option 'noxino' is specified, it
+ will be empty. About XINO files, see the aufs manual.
---- /dev/null
-+++ linux-2.6/fs/aufs/aufs.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
+--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/aufs.h 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -129,9 +537,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/branch.c 2010-11-03 09:26:13.000000000 +0100
-@@ -0,0 +1,1008 @@
+diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/branch.c 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,1051 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -455,11 +864,11 @@
+ * a limit for rmdir/rename a dir
+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
+ */
-+ h_dentry = path->dentry;
-+ err = statfs_by_dentry(h_dentry, &kst);
++ err = vfs_statfs(path, &kst);
+ if (unlikely(err))
+ goto out;
+ err = -EINVAL;
++ h_dentry = path->dentry;
+ if (kst.f_namelen >= NAME_MAX)
+ err = au_br_init_wh(sb, br, perm, h_dentry);
+ else
@@ -488,6 +897,7 @@
+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
+ atomic_set(&br->br_xino_running, 0);
+ br->br_id = au_new_br_id(sb);
++ AuDebugOn(br->br_id < 0);
+
+ if (au_br_writable(add->perm)) {
+ err = au_wbr_init(br, sb, add->perm, &add->path);
@@ -718,15 +1128,23 @@
+ unsigned int sigen, const unsigned int verbose)
+{
+ int err;
-+ struct inode *i;
++ unsigned long long max, ull;
++ struct inode *i, **array;
+ aufs_bindex_t bstart, bend;
+
++ array = au_iarray_alloc(sb, &max);
++ err = PTR_ERR(array);
++ if (IS_ERR(array))
++ goto out;
++
+ err = 0;
-+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
-+ AuDebugOn(!atomic_read(&i->i_count));
-+ if (!list_empty(&i->i_dentry))
++ AuDbg("b%d\n", bindex);
++ for (ull = 0; !err && ull < max; ull++) {
++ i = array[ull];
++ if (i->i_ino == AUFS_ROOT_INO)
+ continue;
+
++ /* AuDbgInode(i); */
+ if (au_iigen(i) == sigen)
+ ii_read_lock_child(i);
+ else {
@@ -748,12 +1166,13 @@
+ && (!S_ISDIR(i->i_mode) || bstart == bend)) {
+ err = -EBUSY;
+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
-+ ii_read_unlock(i);
-+ break;
++ AuDbgInode(i);
+ }
+ ii_read_unlock(i);
+ }
++ au_iarray_free(array, max);
+
++out:
+ return err;
+}
+
@@ -969,41 +1388,78 @@
+ || do_need_sigen_inc(new, old);
+}
+
++static unsigned long long au_farray_cb(void *a,
++ unsigned long long max __maybe_unused,
++ void *arg)
++{
++ unsigned long long n;
++ struct file **p, *f;
++ struct super_block *sb = arg;
++
++ n = 0;
++ p = a;
++ lg_global_lock(files_lglock);
++ do_file_list_for_each_entry(sb, f) {
++ if (au_fi(f)
++ && !special_file(f->f_dentry->d_inode->i_mode)) {
++ get_file(f);
++ *p++ = f;
++ n++;
++ AuDebugOn(n > max);
++ }
++ } while_file_list_for_each_entry;
++ lg_global_unlock(files_lglock);
++
++ return n;
++}
++
++static struct file **au_farray_alloc(struct super_block *sb,
++ unsigned long long *max)
++{
++ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
++ return au_array_alloc(max, au_farray_cb, sb);
++}
++
++static void au_farray_free(struct file **a, unsigned long long max)
++{
++ unsigned long long ull;
++
++ for (ull = 0; ull < max; ull++)
++ if (a[ull])
++ fput(a[ull]);
++ au_array_free(a);
++}
++
+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
+{
-+ int err;
-+ unsigned long n, ul, bytes, files;
++ int err, do_warn;
++ unsigned long long ull, max;
+ aufs_bindex_t br_id;
-+ struct file *file, *hf, **a;
++ struct file *file, *hf, **array;
+ struct dentry *dentry;
+ struct inode *inode;
+ struct au_hfile *hfile;
-+ const int step_bytes = 1024, /* memory allocation unit */
-+ step_files = step_bytes / sizeof(*a);
+
-+ err = -ENOMEM;
-+ n = 0;
-+ bytes = step_bytes;
-+ files = step_files;
-+ a = kmalloc(bytes, GFP_NOFS);
-+ if (unlikely(!a))
++ array = au_farray_alloc(sb, &max);
++ err = PTR_ERR(array);
++ if (IS_ERR(array))
+ goto out;
+
-+ /* no need file_list_lock() since sbinfo is locked? defered? */
++ do_warn = 0;
+ br_id = au_sbr_id(sb, bindex);
-+ do_file_list_for_each_entry(sb, file) {
-+ if (special_file(file->f_dentry->d_inode->i_mode))
-+ continue;
++ for (ull = 0; ull < max; ull++) {
++ file = array[ull];
+ dentry = file->f_dentry;
+ inode = dentry->d_inode;
+
-+ AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
++ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
+ fi_read_lock(file);
+ if (unlikely(au_test_mmapped(file))) {
+ err = -EBUSY;
++ AuDbgFile(file);
+ FiMustNoWaiters(file);
+ fi_read_unlock(file);
-+ goto out_free;
++ goto out_array;
+ }
+
+ hfile = &au_fi(file)->fi_htop;
@@ -1011,39 +1467,33 @@
+ if (!S_ISREG(inode->i_mode)
+ || !(file->f_mode & FMODE_WRITE)
+ || hfile->hf_br->br_id != br_id
-+ || !(hf->f_mode & FMODE_WRITE)) {
-+ FiMustNoWaiters(file);
-+ fi_read_unlock(file);
-+ continue;
++ || !(hf->f_mode & FMODE_WRITE))
++ array[ull] = NULL;
++ else {
++ do_warn = 1;
++ get_file(file);
+ }
+
+ FiMustNoWaiters(file);
+ fi_read_unlock(file);
-+
-+ if (n < files)
-+ a[n++] = hf;
-+ else {
-+ void *p;
-+
-+ err = -ENOMEM;
-+ bytes += step_bytes;
-+ files += step_files;
-+ p = krealloc(a, bytes, GFP_NOFS);
-+ if (p) {
-+ a = p;
-+ a[n++] = hf;
-+ } else
-+ goto out_free;
-+ }
-+ } while_file_list_for_each_entry;
++ fput(file);
++ }
+
+ err = 0;
-+ if (n)
++ if (do_warn)
+ au_warn_ima();
-+ for (ul = 0; ul < n; ul++) {
++
++ for (ull = 0; ull < max; ull++) {
++ file = array[ull];
++ if (!file)
++ continue;
++
+ /* todo: already flushed? */
+ /* cf. fs/super.c:mark_files_ro() */
-+ hf = a[ul];
++ /* fi_read_lock(file); */
++ hfile = &au_fi(file)->fi_htop;
++ hf = hfile->hf_file;
++ /* fi_read_unlock(file); */
+ hf->f_mode &= ~FMODE_WRITE;
+ if (!file_check_writeable(hf)) {
+ file_release_write(hf);
@@ -1051,14 +1501,15 @@
+ }
+ }
+
-+out_free:
-+ kfree(a);
++out_array:
++ au_farray_free(array, max);
+out:
++ AuTraceErr(err);
+ return err;
+}
+
+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
-+ int *do_update)
++ int *do_refresh)
+{
+ int err, rerr;
+ aufs_bindex_t bindex;
@@ -1133,15 +1584,17 @@
+ }
+
+ if (!err) {
-+ *do_update |= need_sigen_inc(br->br_perm, mod->perm);
++ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
+ br->br_perm = mod->perm;
+ }
+
+out:
++ AuTraceErr(err);
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/branch.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/branch.h 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -1289,7 +1742,7 @@
+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
+struct au_opt_mod;
+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
-+ int *do_update);
++ int *do_refresh);
+
+/* xino.c */
+static const loff_t au_loff_max = LLONG_MAX;
@@ -1367,8 +1820,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_BRANCH_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/conf.mk 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
+--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/conf.mk 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,37 @@
+
+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
@@ -1381,7 +1835,7 @@
+
+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
+ SBILIST \
-+ HNOTIFY HFSNOTIFY HINOTIFY \
++ HNOTIFY HFSNOTIFY \
+ EXPORT INO_T_64 \
+ RDU \
+ SP_IATTR \
@@ -1407,8 +1861,9 @@
+${obj}/sysfs.o: ${AuConfName}
+
+-include ${srctree}/${src}/conf_priv.mk
---- /dev/null
-+++ linux-2.6/fs/aufs/cpup.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/cpup.c 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,1059 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -2469,9 +2924,10 @@
+ dput(parent);
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/cpup.h 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,81 @@
+diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
+--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/cpup.h 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -2520,8 +2976,10 @@
+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
+ for link(2) */
+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
-+#define au_fset_cpup(flags, name) { (flags) |= AuCpup_##name; }
-+#define au_fclr_cpup(flags, name) { (flags) &= ~AuCpup_##name; }
++#define au_fset_cpup(flags, name) \
++ do { (flags) |= AuCpup_##name; } while (0)
++#define au_fclr_cpup(flags, name) \
++ do { (flags) &= ~AuCpup_##name; } while (0)
+
+int au_copy_file(struct file *dst, struct file *src, loff_t len);
+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
@@ -2553,8 +3011,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_CPUP_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/dbgaufs.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
+--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dbgaufs.c 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -2890,8 +3349,9 @@
+ err = 0;
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/dbgaufs.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
+--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dbgaufs.h 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -2945,8 +3405,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __DBGAUFS_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/dcsub.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
+--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dcsub.c 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -3148,9 +3609,10 @@
+
+ return path_is_under(path + 0, path + 1);
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/dcsub.h 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,54 @@
+diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
+--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dcsub.h 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -3178,6 +3640,7 @@
+
+#ifdef __KERNEL__
+
++#include <linux/dcache.h>
+#include <linux/types.h>
+
+struct dentry;
@@ -3194,6 +3657,7 @@
+
+/* ---------------------------------------------------------------------- */
+
++/* dcsub.c */
+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
+void au_dpages_free(struct au_dcsub_pages *dpages);
+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
@@ -3203,11 +3667,19 @@
+ int do_include, au_dpages_test test, void *arg);
+int au_test_subdir(struct dentry *d1, struct dentry *d2);
+
++/* ---------------------------------------------------------------------- */
++
++static inline int au_d_removed(struct dentry *d)
++{
++ return !IS_ROOT(d) && d_unhashed(d);
++}
++
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DCSUB_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/debug.c 2010-10-26 21:35:34.000000000 +0200
-@@ -0,0 +1,442 @@
+diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
+--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/debug.c 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -3231,6 +3703,7 @@
+ */
+
+#include <linux/module.h>
++#include <linux/vt_kern.h>
+#include "aufs.h"
+
+int aufs_debug;
@@ -3587,26 +4060,12 @@
+
+void au_dbg_verify_kthread(void)
+{
-+ struct task_struct *tsk = current;
-+
-+ if ((tsk->flags & PF_KTHREAD)
-+ && !strncmp(tsk->comm, AUFS_WKQ_NAME "/", sizeof(AUFS_WKQ_NAME))) {
++ if (current->flags & PF_WQ_WORKER) {
+ au_dbg_blocked();
-+ BUG();
++ WARN_ON(1);
+ }
+}
+
-+static void au_dbg_do_verify_wkq(void *args)
-+{
-+ BUG_ON(current_fsuid());
-+ BUG_ON(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
-+}
-+
-+void au_dbg_verify_wkq(void)
-+{
-+ au_wkq_wait(au_dbg_do_verify_wkq, NULL);
-+}
-+
+/* ---------------------------------------------------------------------- */
+
+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
@@ -3650,9 +4109,10 @@
+
+ return 0;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/debug.h 2010-10-26 21:35:59.000000000 +0200
-@@ -0,0 +1,241 @@
+diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
+--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/debug.h 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -3682,10 +4142,13 @@
+
+#include <asm/system.h>
+#include <linux/bug.h>
++/* #include <linux/err.h> */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
++/* #include <linux/kernel.h> */
+#include <linux/delay.h>
++/* #include <linux/kd.h> */
+#include <linux/sysrq.h>
+#include <linux/aufs_type.h>
+
@@ -3788,7 +4251,6 @@
+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
+void au_dbg_verify_kthread(void);
-+void au_dbg_verify_wkq(void);
+
+int __init au_debug_init(void);
+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
@@ -3854,7 +4316,6 @@
+ unsigned int sigen)
+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
+AuStubVoid(au_dbg_verify_kthread, void)
-+AuStubVoid(au_dbg_verify_wkq, void)
+AuStubInt0(__init au_debug_init, void)
+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
+
@@ -3894,9 +4355,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DEBUG_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/dentry.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,860 @@
+diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dentry.c 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,863 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -3981,8 +4443,10 @@
+
+#define AuLkup_ALLOW_NEG 1
+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
-+#define au_fset_lkup(flags, name) { (flags) |= AuLkup_##name; }
-+#define au_fclr_lkup(flags, name) { (flags) &= ~AuLkup_##name; }
++#define au_fset_lkup(flags, name) \
++ do { (flags) |= AuLkup_##name; } while (0)
++#define au_fclr_lkup(flags, name) \
++ do { (flags) &= ~AuLkup_##name; } while (0)
+
+struct au_do_lookup_args {
+ unsigned int flags;
@@ -4528,8 +4992,9 @@
+ name = &dentry->d_name;
+
+ /*
-+ * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
-+ * But inotify doesn't fire some necessary events,
++ * Theoretically, REVAL test should be unnecessary in case of
++ * {FS,I}NOTIFY.
++ * But {fs,i}notify doesn't fire some necessary events,
+ * IN_ATTRIB for atime/nlink/pageio
+ * IN_DELETE for NFS dentry
+ * Let's do REVAL test too.
@@ -4757,8 +5222,9 @@
+ .d_revalidate = aufs_d_revalidate,
+ .d_release = aufs_d_release
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/dentry.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
+--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dentry.h 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -4991,8 +5457,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DENTRY_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/dinfo.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
+--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dinfo.c 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -5369,7 +5836,7 @@
+ struct dentry *h_dentry;
+
+ bstart = au_dbstart(dentry);
-+ for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
++ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
+ h_dentry = au_h_dptr(dentry, bindex);
+ if (!h_dentry)
+ continue;
@@ -5391,9 +5858,10 @@
+ return bindex;
+ return -1;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/dir.c 2010-10-26 21:41:15.000000000 +0200
-@@ -0,0 +1,638 @@
+diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
+--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dir.c 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -5599,10 +6067,12 @@
+ struct file *file)
+{
+ struct au_vdir *vdir_cache;
++ struct super_block *sb;
+ struct au_finfo *finfo;
+ struct au_fidir *fidir;
+ aufs_bindex_t bindex, bend;
+
++ sb = file->f_dentry->d_sb;
+ finfo = au_fi(file);
+ fidir = finfo->fi_hdir;
+ if (fidir) {
@@ -5822,8 +6292,10 @@
+#define AuTestEmpty_CALLED (1 << 1)
+#define AuTestEmpty_SHWH (1 << 2)
+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
-+#define au_fset_testempty(flags, name) { (flags) |= AuTestEmpty_##name; }
-+#define au_fclr_testempty(flags, name) { (flags) &= ~AuTestEmpty_##name; }
++#define au_fset_testempty(flags, name) \
++ do { (flags) |= AuTestEmpty_##name; } while (0)
++#define au_fclr_testempty(flags, name) \
++ do { (flags) &= ~AuTestEmpty_##name; } while (0)
+
+#ifndef CONFIG_AUFS_SHWH
+#undef AuTestEmpty_SHWH
@@ -6032,8 +6504,9 @@
+ .flush = aufs_flush_dir,
+ .fsync = aufs_fsync_dir
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/dir.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
+--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dir.h 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -6173,8 +6646,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DIR_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/dynop.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
+--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dynop.c 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2010 Junjiro R. Okajima
@@ -6601,8 +7075,9 @@
+ for (i = 0; i < AuDyLast; i++)
+ WARN_ON(!list_empty(&dynop[i].head));
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/dynop.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
+--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/dynop.h 2010-11-22 11:52:56.983894369 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 Junjiro R. Okajima
@@ -6693,8 +7168,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DYNOP_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/export.c 2010-10-26 21:38:27.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
+--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/export.c 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,790 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -7486,9 +7962,10 @@
+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
+ atomic_set(&sbinfo->si_xigen_next, u);
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/file.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,652 @@
+diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/file.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,655 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -7545,8 +8022,10 @@
+ h_inode = h_dentry->d_inode;
+ if (au_test_nfsd() && !h_inode)
+ goto out;
-+ if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
-+ || !h_inode))
++ if (unlikely((!d_unhashed(dentry) && au_d_removed(h_dentry))
++ || !h_inode
++ /* || !dentry->d_inode->i_nlink */
++ ))
+ goto out;
+
+ sb = dentry->d_sb;
@@ -7856,7 +8335,8 @@
+
+ di_read_lock_parent(parent, AuLock_IR);
+ hi_wh = au_hi_wh(inode, bstart);
-+ if (au_opt_test(au_mntflags(sb), PLINK)
++ if (!S_ISDIR(inode->i_mode)
++ && au_opt_test(au_mntflags(sb), PLINK)
+ && au_plink_test(inode)
+ && !d_unhashed(dentry)) {
+ err = au_test_and_cpup_dirs(dentry, bstart);
@@ -7925,7 +8405,7 @@
+ }
+
+ p = fidir->fd_hfile;
-+ if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
++ if (!au_test_mmapped(file) && !au_d_removed(file->f_dentry)) {
+ bend = au_sbend(sb);
+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
+ finfo->fi_btop++, p++)
@@ -7989,7 +8469,7 @@
+ need_reopen = 1;
+ if (!au_test_mmapped(file))
+ err = au_file_refresh_by_inode(file, &need_reopen);
-+ if (!err && need_reopen && !d_unhashed(dentry))
++ if (!err && need_reopen && !au_d_removed(dentry))
+ err = reopen(file);
+ if (!err) {
+ au_update_figen(file);
@@ -8141,8 +8621,9 @@
+ .error_remove_page = aufs_error_remove_page
+#endif /* CONFIG_AUFS_DEBUG */
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/file.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
+--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/file.h 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -8382,9 +8863,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_FILE_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/finfo.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,171 @@
+diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
+--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/finfo.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -8513,6 +8995,8 @@
+{
+ struct au_finfo *finfo;
+
++ au_nfiles_dec(file->f_dentry->d_sb);
++
+ finfo = au_fi(file);
+ AuDebugOn(finfo->fi_hdir);
+ AuRwDestroy(&finfo->fi_rwsem);
@@ -8545,6 +9029,7 @@
+ goto out;
+
+ err = 0;
++ au_nfiles_inc(dentry->d_sb);
+ au_rw_write_lock(&finfo->fi_rwsem);
+ finfo->fi_btop = -1;
+ finfo->fi_hdir = fidir;
@@ -8556,9 +9041,10 @@
+out:
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/f_op.c 2010-10-26 21:39:38.000000000 +0200
-@@ -0,0 +1,900 @@
+diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
+--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/f_op.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,901 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -8646,6 +9132,7 @@
+ file_sb_list_del(file);
+ au_set_h_fptr(file, bindex, NULL);
+ }
++
+ au_finfo_fin(file);
+ return 0;
+}
@@ -9459,8 +9946,9 @@
+ .aio_splice_read = aufs_aio_splice_read
+#endif
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/f_op_sp.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
+--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/f_op_sp.c 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -9761,8 +10249,9 @@
+
+ return ret;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/fstype.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
+--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/fstype.h 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -10261,9 +10750,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_FSTYPE_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/hfsnotify.c 2010-10-26 10:55:35.000000000 +0200
-@@ -0,0 +1,213 @@
+diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
+--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/hfsnotify.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -10292,25 +10782,32 @@
+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 DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
+
+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
+{
-+#if 0
+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
+ hn_mark);
-+ au_cache_free_hnotify(hn);
-+#endif
+ AuDbg("here\n");
++ hn->hn_mark_dead = 1;
++ smp_mb();
++ wake_up_all(&au_hfsn_wq);
+}
+
+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
+{
+ struct fsnotify_mark *mark;
+
++ hn->hn_mark_dead = 0;
+ mark = &hn->hn_mark;
+ fsnotify_init_mark(mark, au_hfsn_free_mark);
+ mark->mask = AuHfsnMask;
-+ return fsnotify_add_mark(mark, au_hfsn_group, h_inode, NULL, 1);
++ /*
++ * by udba rename or rmdir, aufs assign a new inode to the known
++ * h_inode, so specify 1 to allow dups.
++ */
++ return fsnotify_add_mark(mark, au_hfsn_group, h_inode, /*mnt*/NULL,
++ /*allow_dups*/1);
+}
+
+static void au_hfsn_free(struct au_hnotify *hn)
@@ -10320,6 +10817,9 @@
+ mark = &hn->hn_mark;
+ fsnotify_destroy_mark(mark);
+ fsnotify_put_mark(mark);
++
++ /* TODO: bad approach */
++ wait_event(au_hfsn_wq, hn->hn_mark_dead);
+}
+
+/* ---------------------------------------------------------------------- */
@@ -10418,28 +10918,21 @@
+ AuDebugOn(!inode_mark);
+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
-+ fsnotify_put_mark(inode_mark);
+
+out:
+ return err;
+}
+
-+/* copied from linux/fs/notify/inotify/inotify_fsnotify.c */
++/* 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 *inode,
++static bool au_hfsn_should_send_event(struct fsnotify_group *group,
++ struct inode *h_inode,
+ struct fsnotify_mark *inode_mark,
+ struct fsnotify_mark *vfsmount_mark,
+ __u32 mask, void *data, int data_type)
+{
-+ bool send;
-+
+ mask = (mask & ~FS_EVENT_ON_CHILD);
-+ send = (inode_mark->mask & mask);
-+
-+ /* find took a reference */
-+ fsnotify_put_mark(inode_mark);
-+
-+ return send;
++ return inode_mark->mask & mask;
+}
+
+static struct fsnotify_ops au_hfsn_ops = {
@@ -10477,8 +10970,9 @@
+ .fin = au_hfsn_fin,
+ .init = au_hfsn_init
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/hfsplus.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
+--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/hfsplus.c 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Junjiro R. Okajima
@@ -10538,243 +11032,10 @@
+ au_sbr_put(dentry->d_sb, bindex);
+ }
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/hinotify.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,231 @@
-+/*
-+ * 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"
-+
-+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
-+static struct inotify_handle *au_hin_handle;
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
-+{
-+ int err;
-+ s32 wd;
-+ struct inotify_watch *watch;
-+
-+ 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(&hn->hn_watch);
-+ }
-+
-+out:
-+ return err;
-+}
-+
-+static void au_hin_free(struct au_hnotify *hn)
-+{
-+ int err;
-+
-+ 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);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static void au_hin_ctl(struct au_hinode *hinode, int do_set)
-+{
-+ struct inode *h_inode;
-+ struct inotify_watch *watch;
-+
-+ h_inode = hinode->hi_inode;
-+ IMustLock(h_inode);
-+
-+ /* todo: try inotify_find_update_watch()? */
-+ watch = &hinode->hi_notify->hn_watch;
-+ mutex_lock(&h_inode->inotify_mutex);
-+ /* mutex_lock(&watch->ih->mutex); */
-+ if (do_set) {
-+ AuDebugOn(watch->mask & AuHinMask);
-+ watch->mask |= AuHinMask;
-+ } else {
-+ AuDebugOn(!(watch->mask & AuHinMask));
-+ watch->mask &= ~AuHinMask;
-+ }
-+ /* mutex_unlock(&watch->ih->mutex); */
-+ mutex_unlock(&h_inode->inotify_mutex);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+#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) do { \
-+ conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0; \
-+ } while (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) do { \
-+ conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0; \
-+ } while (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
-+};
---- /dev/null
-+++ linux-2.6/fs/aufs/hnotify.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,662 @@
+diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
+--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/hnotify.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,664 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -11058,8 +11319,10 @@
+#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; }
++#define au_fset_hnjob(flags, name) \
++ do { (flags) |= AuHnJob_##name; } while (0)
++#define au_fclr_hnjob(flags, name) \
++ do { (flags) &= ~AuHnJob_##name; } while (0)
+
+enum {
+ AuHn_CHILD,
@@ -11228,7 +11491,7 @@
+ AuDebugOn(!sb);
+ sbinfo = au_sbi(sb);
+ AuDebugOn(!sbinfo);
-+ si_write_lock(sb, !AuLock_FLUSH | AuLock_NOPLMW);
++ si_write_lock(sb, AuLock_NOPLMW);
+
+ ii_read_lock_parent(a->dir);
+ bfound = -1;
@@ -11437,9 +11700,10 @@
+ if (au_cachep[AuCache_HNOTIFY])
+ au_hn_destroy_cache();
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/iinfo.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,259 @@
+diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
+--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/iinfo.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -11622,6 +11886,7 @@
+ nbr = 1;
+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
+ if (iinfo->ii_hinode) {
++ au_ninodes_inc(sb);
+ for (i = 0; i < nbr; i++)
+ iinfo->ii_hinode[i].hi_id = -1;
+
@@ -11669,6 +11934,7 @@
+ return;
+
+ sb = inode->i_sb;
++ au_ninodes_dec(sb);
+ if (si_pid_test(sb))
+ au_xino_delete_inode(inode, unlinked);
+ else {
@@ -11699,8 +11965,9 @@
+ kfree(iinfo->ii_hinode);
+ AuRwDestroy(&iinfo->ii_rwsem);
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/inode.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
+--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/inode.c 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -12145,9 +12412,10 @@
+ mask |= MAY_READ; /* force permission check */
+ return au_test_h_perm(h_inode, mask);
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/inode.h 2010-10-26 10:58:14.000000000 +0200
-@@ -0,0 +1,514 @@
+diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
+--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/inode.h 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -12185,11 +12453,11 @@
+struct au_hnotify {
+#ifdef CONFIG_AUFS_HNOTIFY
+#ifdef CONFIG_AUFS_HFSNOTIFY
++ /* never use fsnotify_add_vfsmount_mark() */
+ struct fsnotify_mark hn_mark;
-+#else
-+ struct inotify_watch hn_watch;
++ int hn_mark_dead;
+#endif
-+ struct inode *hn_aufs_inode; /* no get/put */
++ struct inode *hn_aufs_inode; /* no get/put */
+#endif
+} ____cacheline_aligned_in_smp;
+
@@ -12225,8 +12493,10 @@
+#define AuPin_DI_LOCKED 1
+#define AuPin_MNT_WRITE (1 << 1)
+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
-+#define au_fset_pin(flags, name) { (flags) |= AuPin_##name; }
-+#define au_fclr_pin(flags, name) { (flags) &= ~AuPin_##name; }
++#define au_fset_pin(flags, name) \
++ do { (flags) |= AuPin_##name; } while (0)
++#define au_fclr_pin(flags, name) \
++ do { (flags) &= ~AuPin_##name; } while (0)
+
+struct au_pin {
+ /* input */
@@ -12284,8 +12554,10 @@
+#define AuWrDir_ADD_ENTRY 1
+#define AuWrDir_ISDIR (1 << 1)
+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
-+#define au_fset_wrdir(flags, name) { (flags) |= AuWrDir_##name; }
-+#define au_fclr_wrdir(flags, name) { (flags) &= ~AuWrDir_##name; }
++#define au_fset_wrdir(flags, name) \
++ do { (flags) |= AuWrDir_##name; } while (0)
++#define au_fclr_wrdir(flags, name) \
++ do { (flags) &= ~AuWrDir_##name; } while (0)
+
+struct au_wr_dir_args {
+ aufs_bindex_t force_btgt;
@@ -12337,8 +12609,10 @@
+#define AuHi_XINO 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; }
++#define au_fset_hi(flags, name) \
++ do { (flags) |= AuHi_##name; } while (0)
++#define au_fclr_hi(flags, name) \
++ do { (flags) &= ~AuHi_##name; } while (0)
+
+#ifndef CONFIG_AUFS_HNOTIFY
+#undef AuHi_HNOTIFY
@@ -12563,12 +12837,10 @@
+ unsigned char lflag)
+{
+ if (pin) {
-+ /* dirty macros require brackets */
-+ if (lflag) {
++ if (lflag)
+ au_fset_pin(pin->flags, DI_LOCKED);
-+ } else {
++ else
+ au_fclr_pin(pin->flags, DI_LOCKED);
-+ }
+ }
+}
+
@@ -12603,7 +12875,7 @@
+int __init au_hnotify_init(void);
+void au_hnotify_fin(void);
+
-+/* hinotify.c */
++/* hfsnotify.c */
+extern const struct au_hnotify_op au_hnotify_op;
+
+static inline
@@ -12662,8 +12934,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_INODE_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/ioctl.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
+--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/ioctl.c 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -12815,8 +13088,9 @@
+}
+#endif
+#endif
---- /dev/null
-+++ linux-2.6/fs/aufs/i_op_add.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/i_op_add.c 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,676 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -13494,9 +13768,10 @@
+out:
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/i_op.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,919 @@
+diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/i_op.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -13561,10 +13836,8 @@
+
+ if (!err)
+ err = devcgroup_inode_permission(h_inode, mask);
-+ if (!err) {
-+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
++ if (!err)
+ err = security_inode_permission(h_inode, mask);
-+ }
+
+#if 0
+ if (!err) {
@@ -13658,14 +13931,18 @@
+ IMustLock(dir);
+
+ sb = dir->i_sb;
-+ si_read_lock(sb, AuLock_FLUSH);
++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++ ret = ERR_PTR(err);
++ if (unlikely(err))
++ goto out;
++
+ ret = ERR_PTR(-ENAMETOOLONG);
+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
-+ goto out;
++ goto out_si;
+ err = au_di_init(dentry);
+ ret = ERR_PTR(err);
+ if (unlikely(err))
-+ goto out;
++ goto out_si;
+
+ parent = dentry->d_parent; /* dir inode is locked */
+ di_read_lock_parent(parent, AuLock_IR);
@@ -13685,13 +13962,16 @@
+ goto out_unlock;
+
+ ret = d_splice_alias(inode, dentry);
-+ if (unlikely(IS_ERR(ret) && inode))
++ if (unlikely(IS_ERR(ret) && inode)) {
+ ii_write_unlock(inode);
++ iput(inode);
++ }
+
+out_unlock:
+ di_write_unlock(dentry);
-+out:
++out_si:
+ si_read_unlock(sb);
++out:
+ return ret;
+}
+
@@ -13974,8 +14254,10 @@
+
+#define AuIcpup_DID_CPUP 1
+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
-+#define au_fset_icpup(flags, name) { (flags) |= AuIcpup_##name; }
-+#define au_fclr_icpup(flags, name) { (flags) &= ~AuIcpup_##name; }
++#define au_fset_icpup(flags, name) \
++ do { (flags) |= AuIcpup_##name; } while (0)
++#define au_fclr_icpup(flags, name) \
++ do { (flags) &= ~AuIcpup_##name; } while (0)
+
+struct au_icpup_args {
+ unsigned char flags;
@@ -14038,7 +14320,7 @@
+
+ h_file = NULL;
+ hi_wh = NULL;
-+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
++ if (au_ftest_icpup(a->flags, DID_CPUP) && au_d_removed(dentry)) {
+ hi_wh = au_hi_wh(inode, a->btgt);
+ if (!hi_wh) {
+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
@@ -14129,6 +14411,7 @@
+ } else {
+ /* fchmod() doesn't pass ia_file */
+ a->udba = au_opt_udba(sb);
++ /* no au_d_removed(), to set UDBA_NONE for root */
+ if (d_unhashed(dentry))
+ a->udba = AuOpt_UDBA_NONE;
+ di_write_lock_child(dentry);
@@ -14233,15 +14516,16 @@
+ struct vfsmount *h_mnt;
+ struct dentry *h_dentry;
+
-+ err = 0;
+ sb = dentry->d_sb;
+ inode = dentry->d_inode;
-+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++ if (unlikely(err))
++ goto out;
+ mnt_flags = au_mntflags(sb);
+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
+
+ /* support fstat(2) */
-+ if (!d_unhashed(dentry) && !udba_none) {
++ if (!au_d_removed(dentry) && !udba_none) {
+ unsigned int sigen = au_sigen(sb);
+ if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
+ di_read_lock_child(dentry, AuLock_IR);
@@ -14251,7 +14535,7 @@
+ err = au_reval_for_attr(dentry, sigen);
+ di_downgrade_lock(dentry, AuLock_IR);
+ if (unlikely(err))
-+ goto out;
++ goto out_unlock;
+ }
+ } else
+ di_read_lock_child(dentry, AuLock_IR);
@@ -14283,13 +14567,16 @@
+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
+ goto out_fill; /* success */
+ }
-+ goto out;
++ AuTraceErr(err);
++ goto out_unlock;
+
+out_fill:
+ generic_fillattr(inode, st);
-+out:
++out_unlock:
+ di_read_unlock(dentry, AuLock_IR);
+ si_read_unlock(sb);
++out:
++ AuTraceErr(err);
+ return err;
+}
+
@@ -14416,8 +14703,9 @@
+ .getattr = aufs_getattr,
+ .truncate_range = aufs_truncate_range
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/i_op_del.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/i_op_del.c 2010-11-22 11:52:56.987228248 +0100
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -14701,17 +14989,17 @@
+/*
+ * when an error happened, remove the created whiteout and revert everything.
+ */
-+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
-+ struct dentry *wh_dentry, struct dentry *dentry,
-+ struct au_dtime *dt)
++static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
++ aufs_bindex_t bwh, struct dentry *wh_dentry,
++ struct dentry *dentry, struct au_dtime *dt)
+{
+ int rerr;
+ struct path h_path = {
+ .dentry = wh_dentry,
-+ .mnt = au_sbr_mnt(dir->i_sb, bwh)
++ .mnt = au_sbr_mnt(dir->i_sb, bindex)
+ };
+
-+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
++ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
+ if (!rerr) {
+ au_set_dbwh(dentry, bwh);
+ au_dtime_revert(dt);
@@ -14767,7 +15055,7 @@
+ }
+
+ if (!err) {
-+ drop_nlink(inode);
++ vfsub_drop_nlink(inode);
+ epilog(dir, dentry, bindex);
+
+ /* update target timestamps */
@@ -14784,7 +15072,7 @@
+ if (wh_dentry) {
+ int rerr;
+
-+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
+ if (rerr)
+ err = rerr;
+ }
@@ -14872,7 +15160,7 @@
+ if (wh_dentry) {
+ int rerr;
+
-+ rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
+ if (rerr)
+ err = rerr;
+ }
@@ -14891,9 +15179,10 @@
+ AuTraceErr(err);
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/i_op_ren.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,980 @@
+diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
+--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/i_op_ren.c 2010-11-22 11:52:56.987228248 +0100
+@@ -0,0 +1,982 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -14931,8 +15220,10 @@
+#define AuRen_DIROPQ (1 << 6)
+#define AuRen_CPUP (1 << 7)
+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
-+#define au_fset_ren(flags, name) { (flags) |= AuRen_##name; }
-+#define au_fclr_ren(flags, name) { (flags) &= ~AuRen_##name; }
++#define au_fset_ren(flags, name) \
++ do { (flags) |= AuRen_##name; } while (0)
++#define au_fclr_ren(flags, name) \
++ do { (flags) &= ~AuRen_##name; } while (0)
+
+struct au_ren_args {
+ struct {
@@ -15874,9 +16165,10 @@
+ AuTraceErr(err);
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/Kconfig 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,182 @@
+diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
+--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/Kconfig 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,180 @@
+config AUFS_FS
+ tristate "Aufs (Advanced multi layered unification filesystem) support"
+ depends on EXPERIMENTAL
@@ -15937,6 +16229,7 @@
+ 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=notify' mount option.
++ Currently there is only one available configuration, "fsnotify".
+ It will have a negative impact to the performance.
+ See detail in aufs.5.
+
@@ -15946,9 +16239,6 @@
+config AUFS_HFSNOTIFY
+ bool "fsnotify"
+ select FSNOTIFY
-+config AUFS_HINOTIFY
-+ bool "inotify (DEPRECATED)"
-+ depends on INOTIFY
+endchoice
+
+config AUFS_EXPORT
@@ -16059,8 +16349,9 @@
+ Automatic configuration for internal use.
+ When aufs supports Magic SysRq, enabled automatically.
+endif
---- /dev/null
-+++ linux-2.6/fs/aufs/loop.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
+--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/loop.c 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -16125,8 +16416,9 @@
+
+ return ret;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/loop.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
+--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/loop.h 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -16170,8 +16462,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_LOOP_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/magic.mk 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
+--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/magic.mk 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,54 @@
+
+# defined in ${srctree}/fs/fuse/inode.c
@@ -16227,9 +16520,10 @@
+ifdef CONFIG_HFSPLUS_FS
+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
+endif
---- /dev/null
-+++ linux-2.6/fs/aufs/Makefile 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,39 @@
+diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
+--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/Makefile 2010-11-22 11:52:56.983894369 +0100
+@@ -0,0 +1,38 @@
+
+include ${src}/magic.mk
+ifeq (${CONFIG_AUFS_FS},m)
@@ -16240,8 +16534,8 @@
+# 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'
++# sparse doesn't allow spaces
++ccflags-y += -D'pr_fmt(fmt)=AUFS_NAME"\040%s:%d:%s[%d]:\040"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 \
@@ -16261,7 +16555,6 @@
+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
@@ -16269,8 +16562,9 @@
+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
---- /dev/null
-+++ linux-2.6/fs/aufs/module.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
+--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/module.c 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -16454,8 +16748,9 @@
+
+module_init(aufs_init);
+module_exit(aufs_exit);
---- /dev/null
-+++ linux-2.6/fs/aufs/module.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
+--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/module.h 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -16548,8 +16843,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_MODULE_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/mtx.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/mtx.h linux/fs/aufs/mtx.h
+--- /usr/share/empty/fs/aufs/mtx.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/mtx.h 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Junjiro R. Okajima
@@ -16599,9 +16895,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_MTX_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/opts.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,1595 @@
+diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/opts.c 2010-11-22 11:52:56.990562128 +0100
+@@ -0,0 +1,1581 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -16821,30 +17118,16 @@
+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
+#ifdef CONFIG_AUFS_HFSNOTIFY
+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
-+#else
-+ {AuOpt_UDBA_HNOTIFY, "inotify"},
+#endif
+#endif
+ {-1, NULL}
+};
+
-+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];
+
-+ val = match_token(str, udbalevel, args);
-+ au_warn_inotify(val, str);
-+ return val;
++ return match_token(str, udbalevel, args);
+}
+
+const char *au_optstr_udba(int udba)
@@ -18197,9 +18480,10 @@
+{
+ return au_mntflags(sb) & AuOptMask_UDBA;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/opts.h 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,207 @@
+diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
+--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/opts.h 2010-11-22 11:52:56.990562128 +0100
+@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -18280,7 +18564,9 @@
+ (flags) &= ~AuOptMask_UDBA; \
+ ((flags) |= AuOpt_##name); \
+} while (0)
-+#define au_opt_clr(flags, name) { ((flags) &= ~AuOpt_##name); }
++#define au_opt_clr(flags, name) do { \
++ ((flags) &= ~AuOpt_##name); \
++} while (0)
+
+static inline unsigned int au_opts_plink(unsigned int mntflags)
+{
@@ -18375,8 +18661,10 @@
+#define AuOpts_TRUNC_XIB (1 << 3)
+#define AuOpts_REFRESH_DYAOP (1 << 4)
+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
-+#define au_fset_opts(flags, name) { (flags) |= AuOpts_##name; }
-+#define au_fclr_opts(flags, name) { (flags) &= ~AuOpts_##name; }
++#define au_fset_opts(flags, name) \
++ do { (flags) |= AuOpts_##name; } while (0)
++#define au_fclr_opts(flags, name) \
++ do { (flags) &= ~AuOpts_##name; } while (0)
+
+struct au_opts {
+ struct au_opt *opt;
@@ -18407,9 +18695,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_OPTS_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/plink.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,483 @@
+diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
+--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/plink.c 2010-11-22 11:52:56.990562128 +0100
+@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -18612,12 +18901,40 @@
+ return rlen;
+}
+
++struct au_do_plink_lkup_args {
++ struct dentry **errp;
++ struct qstr *tgtname;
++ struct dentry *h_parent;
++ struct au_branch *br;
++};
++
++static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
++ struct dentry *h_parent,
++ struct au_branch *br)
++{
++ struct dentry *h_dentry;
++ struct mutex *h_mtx;
++
++ h_mtx = &h_parent->d_inode->i_mutex;
++ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
++ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
++ mutex_unlock(h_mtx);
++ return h_dentry;
++}
++
++static void au_call_do_plink_lkup(void *args)
++{
++ struct au_do_plink_lkup_args *a = args;
++ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
++}
++
+/* lookup the plink-ed @inode under the branch at @bindex */
+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
+{
+ struct dentry *h_dentry, *h_parent;
+ struct au_branch *br;
+ struct inode *h_dir;
++ int wkq_err;
+ char a[PLINK_NAME_LEN];
+ struct qstr tgtname = {
+ .name = a
@@ -18630,10 +18947,20 @@
+ h_dir = h_parent->d_inode;
+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
+
-+ /* always superio. */
-+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
-+ h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
-+ mutex_unlock(&h_dir->i_mutex);
++ if (current_fsuid()) {
++ struct au_do_plink_lkup_args args = {
++ .errp = &h_dentry,
++ .tgtname = &tgtname,
++ .h_parent = h_parent,
++ .br = br
++ };
++
++ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
++ if (unlikely(wkq_err))
++ h_dentry = ERR_PTR(wkq_err);
++ } else
++ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
++
+ return h_dentry;
+}
+
@@ -18648,6 +18975,7 @@
+ struct inode *h_dir;
+
+ h_dir = h_parent->d_inode;
++ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
+again:
+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
+ err = PTR_ERR(h_path.dentry);
@@ -18656,6 +18984,7 @@
+
+ err = 0;
+ /* wh.plink dir is not monitored */
++ /* todo: is it really safe? */
+ if (h_path.dentry->d_inode
+ && h_path.dentry->d_inode != h_dentry->d_inode) {
+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
@@ -18669,6 +18998,7 @@
+ dput(h_path.dentry);
+
+out:
++ mutex_unlock(&h_dir->i_mutex);
+ return err;
+}
+
@@ -18704,7 +19034,6 @@
+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
+
+ /* always superio. */
-+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
+ if (current_fsuid()) {
+ struct do_whplink_args args = {
+ .errp = &err,
@@ -18718,7 +19047,6 @@
+ err = wkq_err;
+ } else
+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
-+ mutex_unlock(&h_dir->i_mutex);
+
+ return err;
+}
@@ -18893,8 +19221,9 @@
+ iput(inode);
+ }
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/poll.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
+--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/poll.c 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -18952,8 +19281,9 @@
+ AuTraceErr((int)mask);
+ return mask;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/procfs.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
+--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/procfs.c 2010-11-22 11:52:56.990562128 +0100
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2010 Junjiro R. Okajima
@@ -19124,9 +19454,10 @@
+out:
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/rdu.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,380 @@
+diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
+--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/rdu.c 2010-11-22 11:52:56.990562128 +0100
+@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -19161,8 +19492,10 @@
+#define AuRdu_CONT (1 << 1)
+#define AuRdu_FULL (1 << 2)
+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
-+#define au_fset_rdu(flags, name) { (flags) |= AuRdu_##name; }
-+#define au_fclr_rdu(flags, name) { (flags) &= ~AuRdu_##name; }
++#define au_fset_rdu(flags, name) \
++ do { (flags) |= AuRdu_##name; } while (0)
++#define au_fclr_rdu(flags, name) \
++ do { (flags) &= ~AuRdu_##name; } while (0)
+
+struct au_rdu_arg {
+ struct aufs_rdu *rdu;
@@ -19507,8 +19840,9 @@
+ return err;
+}
+#endif
---- /dev/null
-+++ linux-2.6/fs/aufs/rwsem.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
+--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/rwsem.h 2010-11-22 11:52:56.993896008 +0100
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -19699,9 +20033,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_RWSEM_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/sbinfo.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,311 @@
+diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
+--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/sbinfo.c 2010-11-22 11:52:56.993896008 +0100
+@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -19790,6 +20125,10 @@
+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
+
++ atomic_long_set(&sbinfo->si_ninodes, 0);
++
++ atomic_long_set(&sbinfo->si_nfiles, 0);
++
+ sbinfo->si_bend = -1;
+
+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
@@ -19875,6 +20214,7 @@
+ sbinfo = au_sbi(sb);
+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
+ br_id = ++sbinfo->si_last_br_id;
++ AuDebugOn(br_id < 0);
+ if (br_id && au_br_index(sb, br_id) < 0)
+ return br_id;
+ }
@@ -20013,8 +20353,9 @@
+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
+ AuDebugOn(1 != (long)p);
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/spl.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
+--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/spl.h 2010-11-22 11:52:56.997229888 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -20082,9 +20423,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_SPL_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/super.c 2010-11-02 08:23:34.000000000 +0100
-@@ -0,0 +1,863 @@
+diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
+--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/super.c 2010-11-22 11:52:56.997229888 +0100
+@@ -0,0 +1,954 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -20112,6 +20454,8 @@
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/statfs.h>
++#include <linux/vmalloc.h>
++#include <linux/writeback.h>
+#include "aufs.h"
+
+/*
@@ -20385,7 +20729,7 @@
+ u64 blocks, bfree, bavail, files, ffree;
+ aufs_bindex_t bend, bindex, i;
+ unsigned char shared;
-+ struct vfsmount *h_mnt;
++ struct path h_path;
+ struct super_block *h_sb;
+
+ blocks = 0;
@@ -20397,8 +20741,8 @@
+ err = 0;
+ bend = au_sbend(sb);
+ for (bindex = bend; bindex >= 0; bindex--) {
-+ h_mnt = au_sbr_mnt(sb, bindex);
-+ h_sb = h_mnt->mnt_sb;
++ h_path.mnt = au_sbr_mnt(sb, bindex);
++ h_sb = h_path.mnt->mnt_sb;
+ shared = 0;
+ for (i = bindex + 1; !shared && i <= bend; i++)
+ shared = (au_sbr_sb(sb, i) == h_sb);
@@ -20406,7 +20750,8 @@
+ continue;
+
+ /* sb->s_root for NFS is unreliable */
-+ err = statfs_by_dentry(h_mnt->mnt_root, buf);
++ h_path.dentry = h_path.mnt->mnt_root;
++ err = vfs_statfs(&h_path, buf);
+ if (unlikely(err))
+ goto out;
+
@@ -20430,15 +20775,18 @@
+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+ int err;
++ struct path h_path;
+ struct super_block *sb;
+
+ /* lock free root dinfo */
+ sb = dentry->d_sb;
+ si_noflush_read_lock(sb);
-+ if (!au_opt_test(au_mntflags(sb), SUM))
++ if (!au_opt_test(au_mntflags(sb), SUM)) {
+ /* sb->s_root for NFS is unreliable */
-+ err = statfs_by_dentry(au_sbr_mnt(sb, 0)->mnt_root, buf);
-+ else
++ h_path.mnt = au_sbr_mnt(sb, 0);
++ h_path.dentry = h_path.mnt->mnt_root;
++ err = vfs_statfs(&h_path, buf);
++ } else
+ err = au_statfs_sum(sb, buf);
+ si_read_unlock(sb);
+
@@ -20469,6 +20817,91 @@
+
+/* ---------------------------------------------------------------------- */
+
++void au_array_free(void *array)
++{
++ if (array) {
++ if (!is_vmalloc_addr(array))
++ kfree(array);
++ else
++ vfree(array);
++ }
++}
++
++void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
++{
++ void *array;
++ unsigned long long n;
++
++ array = NULL;
++ n = 0;
++ if (!*hint)
++ goto out;
++
++ if (*hint > ULLONG_MAX / sizeof(array)) {
++ array = ERR_PTR(-EMFILE);
++ pr_err("hint %llu\n", *hint);
++ goto out;
++ }
++
++ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
++ if (unlikely(!array))
++ array = vmalloc(sizeof(array) * *hint);
++ if (unlikely(!array)) {
++ array = ERR_PTR(-ENOMEM);
++ goto out;
++ }
++
++ n = cb(array, *hint, arg);
++ AuDebugOn(n > *hint);
++
++out:
++ *hint = n;
++ return array;
++}
++
++static unsigned long long au_iarray_cb(void *a,
++ unsigned long long max __maybe_unused,
++ void *arg)
++{
++ unsigned long long n;
++ struct inode **p, *inode;
++ struct list_head *head;
++
++ n = 0;
++ p = a;
++ head = arg;
++ spin_lock(&inode_lock);
++ list_for_each_entry(inode, head, i_sb_list) {
++ if (!is_bad_inode(inode)
++ && au_ii(inode)->ii_bstart >= 0) {
++ au_igrab(inode);
++ *p++ = inode;
++ n++;
++ AuDebugOn(n > max);
++ }
++ }
++ spin_unlock(&inode_lock);
++
++ return n;
++}
++
++struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
++{
++ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
++ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
++}
++
++void au_iarray_free(struct inode **a, unsigned long long max)
++{
++ unsigned long long ull;
++
++ for (ull = 0; ull < max; ull++)
++ iput(a[ull]);
++ au_array_free(a);
++}
++
++/* ---------------------------------------------------------------------- */
++
+/*
+ * refresh dentry and inode at remount time.
+ */
@@ -20948,9 +21381,10 @@
+ /* no need to __module_get() and module_put(). */
+ .owner = THIS_MODULE,
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/super.h 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,488 @@
+diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/super.h 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -21027,6 +21461,11 @@
+ struct radix_tree_root tree;
+ } au_si_pid;
+
++ /*
++ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
++ */
++ atomic_long_t si_ninodes, si_nfiles;
++
+ /* branch management */
+ unsigned int si_generation;
+
@@ -21034,7 +21473,10 @@
+ unsigned char au_si_status;
+
+ aufs_bindex_t si_bend;
-+ aufs_bindex_t si_last_br_id;
++
++ /* dirty trick to keep br_id plus */
++ unsigned int si_last_br_id :
++ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
+ struct au_branch **si_branch;
+
+ /* policy to select a writable branch */
@@ -21158,14 +21600,22 @@
+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
-+#define au_fset_lock(flags, name) { (flags) |= AuLock_##name; }
-+#define au_fclr_lock(flags, name) { (flags) &= ~AuLock_##name; }
++#define au_fset_lock(flags, name) \
++ do { (flags) |= AuLock_##name; } while (0)
++#define au_fclr_lock(flags, name) \
++ do { (flags) &= ~AuLock_##name; } while (0)
+
+/* ---------------------------------------------------------------------- */
+
+/* super.c */
+extern struct file_system_type aufs_fs_type;
+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
++typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
++ void *arg);
++void au_array_free(void *array);
++void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
++struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
++void au_iarray_free(struct inode **a, unsigned long long max);
+
+/* sbinfo.c */
+void au_si_free(struct kobject *kobj);
@@ -21418,6 +21868,28 @@
+ return au_sbi(sb)->si_generation;
+}
+
++static inline void au_ninodes_inc(struct super_block *sb)
++{
++ atomic_long_inc(&au_sbi(sb)->si_ninodes);
++}
++
++static inline void au_ninodes_dec(struct super_block *sb)
++{
++ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
++ atomic_long_dec(&au_sbi(sb)->si_ninodes);
++}
++
++static inline void au_nfiles_inc(struct super_block *sb)
++{
++ atomic_long_inc(&au_sbi(sb)->si_nfiles);
++}
++
++static inline void au_nfiles_dec(struct super_block *sb)
++{
++ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
++ atomic_long_dec(&au_sbi(sb)->si_nfiles);
++}
++
+static inline struct au_branch *au_sbr(struct super_block *sb,
+ aufs_bindex_t bindex)
+{
@@ -21439,8 +21911,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_SUPER_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/sysaufs.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
+--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/sysaufs.c 2010-11-22 11:52:57.000563767 +0100
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -21549,8 +22022,9 @@
+out:
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/sysaufs.h 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
+--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/sysaufs.h 2010-11-22 11:52:57.000563767 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -21657,8 +22131,9 @@
+
+#endif /* __KERNEL__ */
+#endif /* __SYSAUFS_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/sysfs.c 2010-10-25 14:20:44.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
+--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/sysfs.c 2010-11-22 11:52:57.000563767 +0100
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -21910,8 +22385,9 @@
+ br->br_name, err);
+ }
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/sysrq.c 2010-10-26 21:43:12.000000000 +0200
+diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
+--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/sysrq.c 2010-11-22 11:52:57.000563767 +0100
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
@@ -22031,9 +22507,10 @@
+ if (unlikely(err))
+ pr_err("err %d (ignored)\n", err);
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/vdir.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,884 @@
+diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
+--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/vdir.c 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,886 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -22470,8 +22947,10 @@
+#define AuFillVdir_WHABLE (1 << 1)
+#define AuFillVdir_SHWH (1 << 2)
+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
-+#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
-+#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
++#define au_fset_fillvdir(flags, name) \
++ do { (flags) |= AuFillVdir_##name; } while (0)
++#define au_fclr_fillvdir(flags, name) \
++ do { (flags) &= ~AuFillVdir_##name; } while (0)
+
+#ifndef CONFIG_AUFS_SHWH
+#undef AuFillVdir_SHWH
@@ -22918,9 +23397,10 @@
+ /* smp_mb(); */
+ return 0;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/vfsub.c 2010-10-26 21:45:14.000000000 +0200
-@@ -0,0 +1,789 @@
+diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/vfsub.c 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,790 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -23007,8 +23487,8 @@
+
+ path_get(path);
+ file = dentry_open(path->dentry, path->mnt,
-+ flags | vfsub_fmode_to_uint(FMODE_NONOTIFY),
-+ current_cred());
++ flags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
++ current_cred());
+ if (IS_ERR(file))
+ goto out;
+
@@ -23025,8 +23505,9 @@
+{
+ struct file *file;
+
-+ file = filp_open(path, oflags | vfsub_fmode_to_uint(FMODE_NONOTIFY),
-+ mode);
++ file = filp_open(path,
++ oflags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */,
++ mode);
+ if (IS_ERR(file))
+ goto out;
+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
@@ -23710,9 +24191,10 @@
+
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/vfsub.h 2010-11-02 08:19:59.000000000 +0100
-@@ -0,0 +1,208 @@
+diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
+--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/vfsub.h 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -23742,13 +24224,14 @@
+
+#include <linux/fs.h>
+#include <linux/lglock.h>
++#include "debug.h"
+
-+/* ---------------------------------------------------------------------- */
++/* copied from linux/fs/internal.h */
+DECLARE_BRLOCK(vfsmount_lock);
-+DECLARE_LGLOCK(files_lglock);
+extern void file_sb_list_del(struct file *f);
+
-+/* copied from fs/file_table.c */
++/* copied from linux/fs/file_table.c */
++DECLARE_LGLOCK(files_lglock);
+#ifdef CONFIG_SMP
+/*
+ * These macros iterate all files on all CPUs for a given superblock.
@@ -23776,7 +24259,9 @@
+
+#define while_file_list_for_each_entry \
+}
-+#endif /* CONFIG_SMP */
++#endif
++
++/* ---------------------------------------------------------------------- */
+
+/* lock subclass for lower inode */
+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
@@ -23797,6 +24282,14 @@
+
+/* ---------------------------------------------------------------------- */
+
++static inline void vfsub_drop_nlink(struct inode *inode)
++{
++ AuDebugOn(!inode->i_nlink);
++ drop_nlink(inode);
++}
++
++/* ---------------------------------------------------------------------- */
++
+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);
@@ -23921,9 +24414,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_VFSUB_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/wbr_policy.c 2010-11-02 08:24:52.000000000 +0100
-@@ -0,0 +1,696 @@
+diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/wbr_policy.c 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,701 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -23981,8 +24475,10 @@
+#define AuCpdown_MADE_DIR (1 << 2)
+#define AuCpdown_DIROPQ (1 << 3)
+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
-+#define au_fset_cpdown(flags, name) { (flags) |= AuCpdown_##name; }
-+#define au_fclr_cpdown(flags, name) { (flags) &= ~AuCpdown_##name; }
++#define au_fset_cpdown(flags, name) \
++ do { (flags) |= AuCpdown_##name; } while (0)
++#define au_fclr_cpdown(flags, name) \
++ do { (flags) &= ~AuCpdown_##name; } while (0)
+
+struct au_cpdown_dir_args {
+ struct dentry *parent;
@@ -24333,6 +24829,7 @@
+ aufs_bindex_t bindex, bend;
+ int err;
+ unsigned long long b, bavail;
++ struct path h_path;
+ /* reduce the stack usage */
+ struct kstatfs *st;
+
@@ -24355,7 +24852,9 @@
+ continue;
+
+ /* sb->s_root for NFS is unreliable */
-+ err = statfs_by_dentry(br->br_mnt->mnt_root, st);
++ h_path.mnt = br->br_mnt;
++ h_path.dentry = h_path.mnt->mnt_root;
++ err = vfs_statfs(&h_path, st);
+ if (unlikely(err)) {
+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
+ continue;
@@ -24620,9 +25119,10 @@
+ .fin = au_wbr_create_fin_mfs
+ }
+};
---- /dev/null
-+++ linux-2.6/fs/aufs/whout.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,1059 @@
+diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
+--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/whout.c 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,1060 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -25599,8 +26099,9 @@
+
+ if (!err) {
+ if (au_ibstart(dir) == bindex) {
++ /* todo: dir->i_mutex is necessary */
+ au_cpup_attr_timesizes(dir);
-+ drop_nlink(dir);
++ vfsub_drop_nlink(dir);
+ }
+ return 0; /* success */
+ }
@@ -25682,9 +26183,10 @@
+ au_whtmp_rmdir_free(args);
+ }
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/whout.h 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,87 @@
+diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
+--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/whout.h 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -25732,8 +26234,10 @@
+/* diropq flags */
+#define AuDiropq_CREATE 1
+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
-+#define au_fset_diropq(flags, name) { (flags) |= AuDiropq_##name; }
-+#define au_fclr_diropq(flags, name) { (flags) &= ~AuDiropq_##name; }
++#define au_fset_diropq(flags, name) \
++ do { (flags) |= AuDiropq_##name; } while (0)
++#define au_fclr_diropq(flags, name) \
++ do { (flags) &= ~AuDiropq_##name; } while (0)
+
+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
+ unsigned int flags);
@@ -25772,9 +26276,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_WHOUT_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/wkq.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,223 @@
+diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
+--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/wkq.c 2010-11-22 11:52:57.000563767 +0100
+@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -25821,7 +26326,7 @@
+
+struct au_wkinfo {
+ struct work_struct wk;
-+ struct super_block *sb;
++ struct kobject *kobj;
+
+ unsigned int flags; /* see wkq.h */
+
@@ -25837,11 +26342,14 @@
+{
+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
+
++ AuDebugOn(current_fsuid());
++ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
++
+ wkinfo->func(wkinfo->args);
+ if (au_ftest_wkq(wkinfo->flags, WAIT))
+ complete(wkinfo->comp);
+ else {
-+ kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
++ kobject_put(wkinfo->kobj);
+ module_put(THIS_MODULE);
+ kfree(wkinfo);
+ }
@@ -25905,6 +26413,12 @@
+ }
+}
+
++/*
++ * Be careful. It is easy to make deadlock happen.
++ * processA: lock, wkq and wait
++ * processB: wkq and wait, lock in wkq
++ * --> deadlock
++ */
+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
+{
+ int err;
@@ -25942,12 +26456,12 @@
+ err = 0;
+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
+ if (wkinfo) {
-+ wkinfo->sb = sb;
++ wkinfo->kobj = &au_sbi(sb)->si_kobj;
+ wkinfo->flags = !AuWkq_WAIT;
+ wkinfo->func = func;
+ wkinfo->args = args;
+ wkinfo->comp = NULL;
-+ kobject_get(&au_sbi(sb)->si_kobj);
++ kobject_get(wkinfo->kobj);
+ __module_get(THIS_MODULE);
+
+ au_wkq_run(wkinfo, !AuWkq_WAIT);
@@ -25983,7 +26497,9 @@
+
+ err = 0;
+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
-+ au_wkq[i].wkq = create_workqueue(au_wkq[i].name);
++ BUILD_BUG_ON(!WQ_RESCUER);
++ au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
++ WQ_DFL_ACTIVE);
+ if (IS_ERR(au_wkq[i].wkq))
+ err = PTR_ERR(au_wkq[i].wkq);
+ else if (!au_wkq[i].wkq)
@@ -25991,16 +26507,15 @@
+ if (unlikely(err))
+ au_wkq[i].wkq = NULL;
+ }
-+ if (!err)
-+ au_dbg_verify_wkq();
-+ else
++ if (unlikely(err))
+ au_wkq_fin();
+
+ return err;
+}
---- /dev/null
-+++ linux-2.6/fs/aufs/wkq.h 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,88 @@
+diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
+--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/wkq.h 2010-11-22 11:52:57.003897646 +0100
+@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -26053,8 +26568,10 @@
+#define AuWkq_WAIT 1
+#define AuWkq_PRE (1 << 1)
+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
-+#define au_fset_wkq(flags, name) { (flags) |= AuWkq_##name; }
-+#define au_fclr_wkq(flags, name) { (flags) &= ~AuWkq_##name; }
++#define au_fset_wkq(flags, name) \
++ do { (flags) |= AuWkq_##name; } while (0)
++#define au_fclr_wkq(flags, name) \
++ do { (flags) &= ~AuWkq_##name; } while (0)
+
+/* wkq.c */
+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
@@ -26089,9 +26606,10 @@
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_WKQ_H__ */
---- /dev/null
-+++ linux-2.6/fs/aufs/xino.c 2010-10-25 14:20:44.000000000 +0200
-@@ -0,0 +1,1263 @@
+diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
+--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/xino.c 2010-11-22 11:52:57.003897646 +0100
+@@ -0,0 +1,1265 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -26262,7 +26780,8 @@
+
+ path.mnt = base_file->f_vfsmnt;
+ file = vfsub_dentry_open(&path,
-+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
++ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
++ /* | FMODE_NONOTIFY */);
+ if (IS_ERR(file)) {
+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
+ goto out_dput;
@@ -26706,7 +27225,7 @@
+
+out:
+ set_bit(free_bit, p);
-+ sbinfo->si_xib_next_bit++;
++ sbinfo->si_xib_next_bit = free_bit + 1;
+ pindex = sbinfo->si_xib_last_pindex;
+ mutex_unlock(&sbinfo->si_xib_mtx);
+ ino = xib_calc_ino(pindex, free_bit);
@@ -26778,7 +27297,8 @@
+ * 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,
++ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
++ /* | FMODE_NONOTIFY */,
+ S_IRUGO | S_IWUGO);
+ if (IS_ERR(file)) {
+ if (!silent)
@@ -27355,9 +27875,10 @@
+out:
+ return err;
+}
---- /dev/null
-+++ linux-2.6/include/linux/aufs_type.h 2010-11-03 09:30:26.000000000 +0100
-@@ -0,0 +1,198 @@
+diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
+--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
++++ linux/include/linux/aufs_type.h 2010-11-22 11:52:57.003897646 +0100
+@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2005-2010 Junjiro R. Okajima
+ *
@@ -27380,14 +27901,11 @@
+#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.1-standalone.tree-36-UNRELEASED-20101103"
++#define AUFS_VERSION "2.1-standalone.tree-36-20101122"
+
+/* todo? move this to linux-2.6.19/include/magic.h */
+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -27556,420 +28074,4 @@
+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
+
+#endif /* __AUFS_TYPE_H__ */
-aufs2.1 base patch for linux-2.6.35
-
-diff --git a/fs/namei.c b/fs/namei.c
-index 868d0cb..6e92c81 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -1178,7 +1178,7 @@ out:
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--static struct dentry *lookup_hash(struct nameidata *nd)
-+struct dentry *lookup_hash(struct nameidata *nd)
- {
- int err;
-
-@@ -1188,7 +1188,7 @@ static struct dentry *lookup_hash(struct nameidata *nd)
- return __lookup_hash(&nd->last, nd->path.dentry, nd);
- }
-
--static int __lookup_one_len(const char *name, struct qstr *this,
-+int __lookup_one_len(const char *name, struct qstr *this,
- struct dentry *base, int len)
- {
- unsigned long hash;
-diff --git a/fs/splice.c b/fs/splice.c
-index efdbfec..e01a51e 100644
---- a/fs/splice.c
-+++ b/fs/splice.c
-@@ -1104,8 +1104,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
- /*
- * Attempt to initiate a splice from pipe to file.
- */
--static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-- loff_t *ppos, size_t len, unsigned int flags)
-+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-+ loff_t *ppos, size_t len, unsigned int flags)
- {
- ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
- loff_t *, size_t, unsigned int);
-@@ -1132,9 +1132,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
- /*
- * Attempt to initiate a splice from a file to a pipe.
- */
--static long do_splice_to(struct file *in, loff_t *ppos,
-- struct pipe_inode_info *pipe, size_t len,
-- unsigned int flags)
-+long do_splice_to(struct file *in, loff_t *ppos,
-+ struct pipe_inode_info *pipe, size_t len,
-+ unsigned int flags)
- {
- ssize_t (*splice_read)(struct file *, loff_t *,
- struct pipe_inode_info *, size_t, unsigned int);
-diff --git a/include/linux/namei.h b/include/linux/namei.h
-index 05b441d..91bc74e 100644
---- a/include/linux/namei.h
-+++ b/include/linux/namei.h
-@@ -73,6 +73,9 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
- 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 int follow_down(struct path *);
-diff --git a/include/linux/splice.h b/include/linux/splice.h
-index 997c3b4..be9a153 100644
---- a/include/linux/splice.h
-+++ b/include/linux/splice.h
-@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
- extern void splice_shrink_spd(struct pipe_inode_info *,
- struct splice_pipe_desc *);
-
-+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-+ loff_t *ppos, size_t len, unsigned int flags);
-+extern long do_splice_to(struct file *in, loff_t *ppos,
-+ struct pipe_inode_info *pipe, size_t len,
-+ unsigned int flags);
-+
- #endif
-aufs2.1 kbuild patch for linux-2.6.36
-diff --git a/fs/Kconfig b/fs/Kconfig
-index 3d18530..8f582e1 100644
---- a/fs/Kconfig
-+++ b/fs/Kconfig
-@@ -189,6 +189,7 @@ source "fs/romfs/Kconfig"
- source "fs/sysv/Kconfig"
- source "fs/ufs/Kconfig"
- source "fs/exofs/Kconfig"
-+source "fs/aufs/Kconfig"
-
- endif # MISC_FILESYSTEMS
-
-diff --git a/fs/Makefile b/fs/Makefile
-index e6ec1d3..b0d795a 100644
---- a/fs/Makefile
-+++ b/fs/Makefile
-@@ -126,3 +126,4 @@ obj-$(CONFIG_BTRFS_FS) += btrfs/
- obj-$(CONFIG_GFS2_FS) += gfs2/
- obj-$(CONFIG_EXOFS_FS) += exofs/
- obj-$(CONFIG_CEPH_FS) += ceph/
-+obj-$(CONFIG_AUFS_FS) += aufs/
-diff --git a/include/linux/Kbuild b/include/linux/Kbuild
-index 626b629..a841231 100644
---- a/include/linux/Kbuild
-+++ b/include/linux/Kbuild
-@@ -60,6 +60,7 @@ header-y += atmppp.h
- header-y += atmsap.h
- header-y += atmsvc.h
- header-y += audit.h
-+header-y += aufs_type.h
- header-y += auto_fs.h
- header-y += auto_fs4.h
- header-y += auxvec.h
-aufs2.1 standalone patch for linux-2.6.36
-
-diff --git a/fs/inode.c b/fs/inode.c
-index 722860b..bfb0698 100644
---- a/fs/inode.c
-+++ b/fs/inode.c
-@@ -84,6 +84,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
- * the i_state of an inode while it is in use..
- */
- DEFINE_SPINLOCK(inode_lock);
-+EXPORT_SYMBOL_GPL(inode_lock);
-
- /*
- * iprune_sem provides exclusion between the kswapd or try_to_free_pages
-diff --git a/fs/namei.c b/fs/namei.c
-index 56e8ece..ba75f28 100644
---- a/fs/namei.c
-+++ b/fs/namei.c
-@@ -347,6 +347,7 @@ int deny_write_access(struct file * file)
-
- return 0;
- }
-+EXPORT_SYMBOL_GPL(deny_write_access);
-
- /**
- * path_get - get a reference to a path
-@@ -1177,6 +1178,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
- return ERR_PTR(err);
- return __lookup_hash(&nd->last, nd->path.dentry, nd);
- }
-+EXPORT_SYMBOL_GPL(lookup_hash);
-
- int __lookup_one_len(const char *name, struct qstr *this,
- struct dentry *base, int len)
-@@ -1199,6 +1201,7 @@ int __lookup_one_len(const char *name, struct qstr *this,
- this->hash = end_name_hash(hash);
- return 0;
- }
-+EXPORT_SYMBOL_GPL(__lookup_one_len);
-
- /**
- * lookup_one_len - filesystem helper to lookup single pathname component
-diff --git a/fs/namespace.c b/fs/namespace.c
-index 2e10cb1..8fa77c4 100644
---- a/fs/namespace.c
-+++ b/fs/namespace.c
-@@ -1283,6 +1283,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
- }
- return 0;
- }
-+EXPORT_SYMBOL_GPL(iterate_mounts);
-
- static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
- {
-diff --git a/fs/notify/group.c b/fs/notify/group.c
-index d309f38..f0e9568 100644
---- a/fs/notify/group.c
-+++ b/fs/notify/group.c
-@@ -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"
-@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
- if (atomic_dec_and_test(&group->refcnt))
- fsnotify_destroy_group(group);
- }
-+EXPORT_SYMBOL_GPL(fsnotify_put_group);
-
- /*
- * Create a new fsnotify_group and hold a reference for the group returned.
-@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
-
- return group;
- }
-+EXPORT_SYMBOL_GPL(fsnotify_alloc_group);
-diff --git a/fs/notify/mark.c b/fs/notify/mark.c
-index 325185e..adede09 100644
---- a/fs/notify/mark.c
-+++ b/fs/notify/mark.c
-@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
- if (atomic_dec_and_test(&mark->refcnt))
- mark->free_mark(mark);
- }
-+EXPORT_SYMBOL_GPL(fsnotify_put_mark);
-
- /*
- * Any time a mark is getting freed we end up here.
-@@ -190,6 +191,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
- if (unlikely(atomic_dec_and_test(&group->num_marks)))
- fsnotify_final_destroy_group(group);
- }
-+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark);
-
- void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
- {
-@@ -277,6 +279,7 @@ err:
-
- return ret;
- }
-+EXPORT_SYMBOL_GPL(fsnotify_add_mark);
-
- /*
- * clear any marks in a group in which mark->flags & flags is true
-@@ -332,6 +335,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
- atomic_set(&mark->refcnt, 1);
- mark->free_mark = free_mark;
- }
-+EXPORT_SYMBOL_GPL(fsnotify_init_mark);
-
- static int fsnotify_mark_destroy(void *ignored)
- {
-diff --git a/fs/open.c b/fs/open.c
-index 630715f..1c864c7 100644
---- a/fs/open.c
-+++ b/fs/open.c
-@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
- mutex_unlock(&dentry->d_inode->i_mutex);
- return ret;
- }
-+EXPORT_SYMBOL_GPL(do_truncate);
-
- static long do_sys_truncate(const char __user *pathname, loff_t length)
- {
-diff --git a/fs/splice.c b/fs/splice.c
-index 278c94f..033f7ac 100644
---- a/fs/splice.c
-+++ b/fs/splice.c
-@@ -1116,6 +1116,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-
- return splice_write(pipe, out, ppos, len, flags);
- }
-+EXPORT_SYMBOL_GPL(do_splice_from);
-
- /*
- * Attempt to initiate a splice from a file to a pipe.
-@@ -1142,6 +1143,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
-
- return splice_read(in, ppos, pipe, len, flags);
- }
-+EXPORT_SYMBOL_GPL(do_splice_to);
-
- /**
- * splice_direct_to_actor - splices data directly between two non-pipes
-diff --git a/security/commoncap.c b/security/commoncap.c
-index 4e01599..3611e1b 100644
---- a/security/commoncap.c
-+++ b/security/commoncap.c
-@@ -951,3 +951,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
- }
- return ret;
- }
-+EXPORT_SYMBOL_GPL(cap_file_mmap);
-diff --git a/security/device_cgroup.c b/security/device_cgroup.c
-index 8d9c48f..29108aa 100644
---- a/security/device_cgroup.c
-+++ b/security/device_cgroup.c
-@@ -515,6 +515,7 @@ found:
-
- return -EPERM;
- }
-+EXPORT_SYMBOL_GPL(devcgroup_inode_permission);
-
- int devcgroup_inode_mknod(int mode, dev_t dev)
- {
-diff --git a/security/security.c b/security/security.c
-index c53949f..0ae5b91 100644
---- a/security/security.c
-+++ b/security/security.c
-@@ -376,6 +376,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
- return 0;
- return security_ops->path_mkdir(dir, dentry, mode);
- }
-+EXPORT_SYMBOL_GPL(security_path_mkdir);
-
- int security_path_rmdir(struct path *dir, struct dentry *dentry)
- {
-@@ -383,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
- return 0;
- return security_ops->path_rmdir(dir, dentry);
- }
-+EXPORT_SYMBOL_GPL(security_path_rmdir);
-
- int security_path_unlink(struct path *dir, struct dentry *dentry)
- {
-@@ -390,6 +392,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
- return 0;
- return security_ops->path_unlink(dir, dentry);
- }
-+EXPORT_SYMBOL_GPL(security_path_unlink);
-
- int security_path_symlink(struct path *dir, struct dentry *dentry,
- const char *old_name)
-@@ -398,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
- return 0;
- return security_ops->path_symlink(dir, dentry, old_name);
- }
-+EXPORT_SYMBOL_GPL(security_path_symlink);
-
- int security_path_link(struct dentry *old_dentry, struct path *new_dir,
- struct dentry *new_dentry)
-@@ -406,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
- return 0;
- return security_ops->path_link(old_dentry, new_dir, new_dentry);
- }
-+EXPORT_SYMBOL_GPL(security_path_link);
-
- int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
- struct path *new_dir, struct dentry *new_dentry)
-@@ -416,6 +421,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
- return security_ops->path_rename(old_dir, old_dentry, new_dir,
- new_dentry);
- }
-+EXPORT_SYMBOL_GPL(security_path_rename);
-
- int security_path_truncate(struct path *path)
- {
-@@ -423,6 +429,7 @@ int security_path_truncate(struct path *path)
- return 0;
- return security_ops->path_truncate(path);
- }
-+EXPORT_SYMBOL_GPL(security_path_truncate);
-
- int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
- mode_t mode)
-@@ -431,6 +438,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
- return 0;
- return security_ops->path_chmod(dentry, mnt, mode);
- }
-+EXPORT_SYMBOL_GPL(security_path_chmod);
-
- int security_path_chown(struct path *path, uid_t uid, gid_t gid)
- {
-@@ -438,6 +446,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
- return 0;
- return security_ops->path_chown(path, uid, gid);
- }
-+EXPORT_SYMBOL_GPL(security_path_chown);
-
- int security_path_chroot(struct path *path)
- {
-@@ -514,6 +523,7 @@ int security_inode_readlink(struct dentry *dentry)
- return 0;
- return security_ops->inode_readlink(dentry);
- }
-+EXPORT_SYMBOL_GPL(security_inode_readlink);
-
- int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
- {
-@@ -528,6 +538,7 @@ int security_inode_permission(struct inode *inode, int mask)
- return 0;
- return security_ops->inode_permission(inode, mask);
- }
-+EXPORT_SYMBOL_GPL(security_inode_permission);
-
- int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
- {
-@@ -627,6 +638,7 @@ int security_file_permission(struct file *file, int mask)
-
- return fsnotify_perm(file, mask);
- }
-+EXPORT_SYMBOL_GPL(security_file_permission);
-
- int security_file_alloc(struct file *file)
- {
-@@ -654,6 +666,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
- return ret;
- return ima_file_mmap(file, prot);
- }
-+EXPORT_SYMBOL_GPL(security_file_mmap);
-
- int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
- unsigned long prot)
-diff --git a/fs/file_table.c b/fs/file_table.c
-index 44abf87..4081dda 100644
---- a/fs/file_table.c
-+++ b/fs/file_table.c
-@@ -395,6 +395,8 @@ void file_sb_list_del(struct file *file)
- }
- }
-
-+EXPORT_SYMBOL_GPL(file_sb_list_del);
-+
- #ifdef CONFIG_SMP
-
- /*
-diff --git a/fs/statfs.c b/fs/statfs.c
-index 30ea8c8..9025c98 100644
---- a/fs/statfs.c
-+++ b/fs/statfs.c
-@@ -61,6 +61,7 @@ int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
- buf->f_frsize = buf->f_bsize;
- return retval;
- }
-+EXPORT_SYMBOL_GPL(statfs_by_dentry);
-
- int vfs_statfs(struct path *path, struct kstatfs *buf)
- {