diff options
author | Arkadiusz MiĆkiewicz | 2010-11-22 11:36:06 (GMT) |
---|---|---|
committer | cvs2git | 2012-06-24 12:13:13 (GMT) |
commit | 7f207e10d4050e47df14b442a5bec5c522af38ea (patch) | |
tree | cbc238cae38fd5fd074e2421398b68a52b77d9b6 | |
parent | c49e75c6a4848ea8ce322cb73c949cb2d47f7852 (diff) | |
download | kernel-7f207e10d4050e47df14b442a5bec5c522af38ea.zip kernel-7f207e10d4050e47df14b442a5bec5c522af38ea.tar.gz |
official aufs2.1 patch
Changed files:
kernel-aufs2.patch -> 1.15
-rw-r--r-- | kernel-aufs2.patch | 2202 |
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) - { |