[packages/kernel] - updated aufs patch to 3.18.1+
baggins
baggins at pld-linux.org
Sun Jan 25 13:13:33 CET 2015
commit c1595e4220910ac55995380e00392abc3a6e934e
Author: Jan Rękorajski <baggins at pld-linux.org>
Date: Sun Jan 25 13:13:10 2015 +0100
- updated aufs patch to 3.18.1+
kernel-aufs3.patch | 2328 ++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 1803 insertions(+), 525 deletions(-)
---
diff --git a/kernel-aufs3.patch b/kernel-aufs3.patch
index d728d11..68ab2f5 100644
--- a/kernel-aufs3.patch
+++ b/kernel-aufs3.patch
@@ -1,10 +1,10 @@
-aufs3.16 kbuild patch
+aufs3.18.1+ kbuild patch
diff --git a/fs/Kconfig b/fs/Kconfig
-index 312393f..78632ed 100644
+index 664991a..1481093 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
-@@ -209,6 +209,7 @@ source "fs/ufs/Kconfig"
+@@ -210,6 +210,7 @@ source "fs/ufs/Kconfig"
source "fs/exofs/Kconfig"
source "fs/f2fs/Kconfig"
source "fs/efivarfs/Kconfig"
@@ -13,16 +13,16 @@ index 312393f..78632ed 100644
endif # MISC_FILESYSTEMS
diff --git a/fs/Makefile b/fs/Makefile
-index 4030cbf..5bd169a 100644
+index da0bbb4..c8bc724 100644
--- a/fs/Makefile
+++ b/fs/Makefile
-@@ -125,3 +125,4 @@ obj-y += exofs/ # Multiple modules
+@@ -126,3 +126,4 @@ obj-y += exofs/ # Multiple modules
obj-$(CONFIG_CEPH_FS) += ceph/
obj-$(CONFIG_PSTORE) += pstore/
obj-$(CONFIG_EFIVAR_FS) += efivarfs/
+obj-$(CONFIG_AUFS_FS) += aufs/
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
-index 24e9033..fe9a8d4 100644
+index 8523f9b..11f8f74 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -56,6 +56,7 @@ header-y += atmppp.h
@@ -33,8 +33,33 @@ index 24e9033..fe9a8d4 100644
header-y += auto_fs.h
header-y += auto_fs4.h
header-y += auxvec.h
-aufs3.16 base patch
+aufs3.18.1+ base patch
+diff --git a/MAINTAINERS b/MAINTAINERS
+index c721042..83801d0 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1795,6 +1795,20 @@ F: include/linux/audit.h
+ F: include/uapi/linux/audit.h
+ F: kernel/audit*
+
++AUFS (advanced multi layered unification filesystem) FILESYSTEM
++M: "J. R. Okajima" <hooanon05g at gmail.com>
++L: linux-unionfs at vger.kernel.org
++L: aufs-users at lists.sourceforge.net (members only)
++W: http://aufs.sourceforge.net
++T: git://git.code.sf.net/p/aufs/aufs3-linux
++T: git://github.com/sfjro/aufs3-linux.git
++S: Supported
++F: Documentation/filesystems/aufs/
++F: Documentation/ABI/testing/debugfs-aufs
++F: Documentation/ABI/testing/sysfs-aufs
++F: fs/aufs/
++F: include/uapi/linux/aufs_type.h
++
+ AUXILIARY DISPLAY DRIVERS
+ M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis at gmail.com>
+ W: http://miguelojeda.es/auxdisplay.htm
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6cb1beb..30efd68 100644
--- a/drivers/block/loop.c
@@ -64,11 +89,24 @@ index 6cb1beb..30efd68 100644
/* loop sysfs attributes */
static ssize_t loop_attr_show(struct device *dev, char *page,
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 71acf8d..da7342e 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1019,7 +1019,7 @@ enum d_walk_ret {
+ *
+ * The @enter() and @finish() callbacks are called with d_lock held.
+ */
+-static void d_walk(struct dentry *parent, void *data,
++void d_walk(struct dentry *parent, void *data,
+ enum d_walk_ret (*enter)(void *, struct dentry *),
+ void (*finish)(void *))
+ {
diff --git a/fs/inode.c b/fs/inode.c
-index 6eecb7f..b225c0f 100644
+index 26753ba..df21e66 100644
--- a/fs/inode.c
+++ b/fs/inode.c
-@@ -1496,7 +1496,7 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
+@@ -1497,7 +1497,7 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
* This does the actual work of updating an inodes time or version. Must have
* had called mnt_want_write() before calling this.
*/
@@ -78,7 +116,7 @@ index 6eecb7f..b225c0f 100644
if (inode->i_op->update_time)
return inode->i_op->update_time(inode, time, flags);
diff --git a/fs/splice.c b/fs/splice.c
-index f5cb9ba..9ba380c 100644
+index 75c6058..619359a 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1114,8 +1114,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
@@ -106,10 +144,10 @@ index f5cb9ba..9ba380c 100644
ssize_t (*splice_read)(struct file *, loff_t *,
struct pipe_inode_info *, size_t, unsigned int);
diff --git a/include/linux/fs.h b/include/linux/fs.h
-index e11d60c..2f32b35 100644
+index 9ab779e..aabcbba 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
-@@ -2618,6 +2618,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *);
+@@ -2664,6 +2664,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *);
extern int inode_newsize_ok(const struct inode *, loff_t offset);
extern void setattr_copy(struct inode *inode, const struct iattr *attr);
@@ -132,13 +170,13 @@ index da2751d..2e0fca6 100644
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags);
#endif
-aufs3.16 mmap patch
+aufs3.18.1+ mmap patch
diff --git a/fs/buffer.c b/fs/buffer.c
-index eba6e4f..31f0b2d 100644
+index 20805db..363569f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
-@@ -2460,7 +2460,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
+@@ -2450,7 +2450,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
* Update file times before taking page lock. We may end up failing the
* fault so this update may be superfluous but who really cares...
*/
@@ -147,6 +185,19 @@ index eba6e4f..31f0b2d 100644
ret = __block_page_mkwrite(vma, vmf, get_block);
sb_end_pagefault(sb);
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 772efa4..2c944de 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -1735,7 +1735,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path)
+ down_read(&mm->mmap_sem);
+ vma = find_exact_vma(mm, vm_start, vm_end);
+ if (vma && vma->vm_file) {
+- *path = vma->vm_file->f_path;
++ *path = vma_pr_or_file(vma)->f_path;
+ path_get(path);
+ rc = 0;
+ }
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index d4a3574..1397181 100644
--- a/fs/proc/nommu.c
@@ -164,10 +215,10 @@ index d4a3574..1397181 100644
ino = inode->i_ino;
}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
-index cfa63ee..bf4919e 100644
+index 4e0388c..fc429e7 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
-@@ -265,7 +265,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
+@@ -276,7 +276,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
const char *name = NULL;
if (file) {
@@ -179,7 +230,7 @@ index cfa63ee..bf4919e 100644
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
-@@ -1390,7 +1393,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
+@@ -1440,7 +1443,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
struct vm_area_struct *vma = v;
struct numa_maps *md = &numa_priv->md;
@@ -189,10 +240,10 @@ index cfa63ee..bf4919e 100644
struct mm_walk walk = {};
struct mempolicy *pol;
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
-index 678455d..0ef7ef4 100644
+index 599ec2e..de6cd6e 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
-@@ -141,7 +141,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
+@@ -160,7 +160,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
file = vma->vm_file;
if (file) {
@@ -205,10 +256,10 @@ index 678455d..0ef7ef4 100644
ino = inode->i_ino;
pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
diff --git a/include/linux/mm.h b/include/linux/mm.h
-index e03dd29..dd32624 100644
+index b464611..8027d51 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
-@@ -1184,6 +1184,28 @@ static inline int fixup_user_fault(struct task_struct *tsk,
+@@ -1206,6 +1206,28 @@ static inline int fixup_user_fault(struct task_struct *tsk,
}
#endif
@@ -238,7 +289,7 @@ index e03dd29..dd32624 100644
extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
void *buf, int len, int write);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
-index 96c5750..a087ecd 100644
+index 6e0b286..8f374ed 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -232,6 +232,7 @@ struct vm_region {
@@ -258,10 +309,10 @@ index 96c5750..a087ecd 100644
#ifndef CONFIG_MMU
diff --git a/kernel/fork.c b/kernel/fork.c
-index 6a13c46..714302c 100644
+index 9b7d746..9a3b8fe 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
-@@ -416,7 +416,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+@@ -430,7 +430,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
struct inode *inode = file_inode(file);
struct address_space *mapping = file->f_mapping;
@@ -271,23 +322,23 @@ index 6a13c46..714302c 100644
atomic_dec(&inode->i_writecount);
mutex_lock(&mapping->i_mmap_mutex);
diff --git a/mm/Makefile b/mm/Makefile
-index 4064f3e..0003fdf 100644
+index 8405eb0..e0bda2d 100644
--- a/mm/Makefile
+++ b/mm/Makefile
-@@ -18,7 +18,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
+@@ -18,7 +18,7 @@ obj-y := filemap.o mempool.o oom_kill.o \
mm_init.o mmu_context.o percpu.o slab_common.o \
- compaction.o balloon_compaction.o vmacache.o \
+ compaction.o vmacache.o \
interval_tree.o list_lru.o workingset.o \
- iov_iter.o debug.o $(mmu-y)
-+ iov_iter.o debug.o prfile.o $(mmu-y)
++ iov_iter.o prfile.o debug.o $(mmu-y)
obj-y += init-mm.o
diff --git a/mm/filemap.c b/mm/filemap.c
-index 900edfa..f4dda0c 100644
+index 14b4642..99bc835 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
-@@ -2040,7 +2040,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+@@ -2067,7 +2067,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
int ret = VM_FAULT_LOCKED;
sb_start_pagefault(inode->i_sb);
@@ -332,10 +383,10 @@ index 72b8fa3..a00bbf0 100644
}
goto out_freed;
diff --git a/mm/madvise.c b/mm/madvise.c
-index a402f8f..134e15d 100644
+index 0938b30..0b66856 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
-@@ -327,12 +327,12 @@ static long madvise_remove(struct vm_area_struct *vma,
+@@ -324,12 +324,12 @@ static long madvise_remove(struct vm_area_struct *vma,
* vma's reference to the file) can go away as soon as we drop
* mmap_sem.
*/
@@ -351,10 +402,10 @@ index a402f8f..134e15d 100644
return error;
}
diff --git a/mm/memory.c b/mm/memory.c
-index 8b44f76..69a72bf 100644
+index d5f2ae9..0830a96 100644
--- a/mm/memory.c
+++ b/mm/memory.c
-@@ -2161,7 +2161,7 @@ reuse:
+@@ -2163,7 +2163,7 @@ reuse:
set_page_dirty_balance(dirty_page);
/* file_update_time outside page_lock */
if (vma->vm_file)
@@ -364,10 +415,10 @@ index 8b44f76..69a72bf 100644
put_page(dirty_page);
if (page_mkwrite) {
diff --git a/mm/mmap.c b/mm/mmap.c
-index 129b847..869d1d7 100644
+index ae91989..e3bee5c 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
-@@ -253,7 +253,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
+@@ -277,7 +277,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
if (vma->vm_file)
@@ -376,7 +427,7 @@ index 129b847..869d1d7 100644
mpol_put(vma_policy(vma));
kmem_cache_free(vm_area_cachep, vma);
return next;
-@@ -863,7 +863,7 @@ again: remove_next = 1 + (end > next->vm_end);
+@@ -895,7 +895,7 @@ again: remove_next = 1 + (end > next->vm_end);
if (remove_next) {
if (file) {
uprobe_munmap(next, next->vm_start, next->vm_end);
@@ -385,7 +436,7 @@ index 129b847..869d1d7 100644
}
if (next->anon_vma)
anon_vma_merge(vma, next);
-@@ -1643,8 +1643,8 @@ out:
+@@ -1680,8 +1680,8 @@ out:
return addr;
unmap_and_free_vma:
@@ -395,7 +446,7 @@ index 129b847..869d1d7 100644
/* Undo any partial mapping done by a device driver. */
unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
-@@ -2434,7 +2434,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
+@@ -2477,7 +2477,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
goto out_free_mpol;
if (new->vm_file)
@@ -404,7 +455,7 @@ index 129b847..869d1d7 100644
if (new->vm_ops && new->vm_ops->open)
new->vm_ops->open(new);
-@@ -2453,7 +2453,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
+@@ -2496,7 +2496,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
if (new->vm_ops && new->vm_ops->close)
new->vm_ops->close(new);
if (new->vm_file)
@@ -413,7 +464,7 @@ index 129b847..869d1d7 100644
unlink_anon_vmas(new);
out_free_mpol:
mpol_put(vma_policy(new));
-@@ -2842,7 +2842,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
+@@ -2886,7 +2886,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
if (anon_vma_clone(new_vma, vma))
goto out_free_mempol;
if (new_vma->vm_file)
@@ -443,7 +494,7 @@ index 992a167..ce1915b 100644
goto out;
down_read(&mm->mmap_sem);
diff --git a/mm/nommu.c b/mm/nommu.c
-index 4a852f6..b369644 100644
+index bd1808e..c9ea035 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -658,7 +658,7 @@ static void __put_nommu_region(struct vm_region *region)
@@ -578,10 +629,22 @@ index 0000000..fc708d2
+ fput(pr);
+}
+#endif /* CONFIG_MMU */
-aufs3.16 standalone patch
+aufs3.18.1+ standalone patch
+diff --git a/fs/dcache.c b/fs/dcache.c
+index da7342e..b147b6c 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1124,6 +1124,7 @@ rename_retry:
+ seq = 1;
+ goto again;
+ }
++EXPORT_SYMBOL(d_walk);
+
+ /*
+ * Search for at least 1 mount point in the dentry's subdirs.
diff --git a/fs/inode.c b/fs/inode.c
-index b225c0f..73259c8 100644
+index df21e66..c8df03d 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -57,6 +57,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
@@ -592,7 +655,7 @@ index b225c0f..73259c8 100644
/*
* Empty aops. Can be used for the cases where the user does not
-@@ -1512,6 +1513,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags)
+@@ -1513,6 +1514,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags)
mark_inode_dirty_sync(inode);
return 0;
}
@@ -601,10 +664,10 @@ index b225c0f..73259c8 100644
/**
* touch_atime - update the access time
diff --git a/fs/namespace.c b/fs/namespace.c
-index 182bc41..c88e101 100644
+index 5b66b2b..68ff4e4 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
-@@ -453,6 +453,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
+@@ -454,6 +454,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
mnt_dec_writers(real_mount(mnt));
preempt_enable();
}
@@ -612,7 +675,7 @@ index 182bc41..c88e101 100644
/**
* mnt_drop_write - give up write access to a mount
-@@ -1564,6 +1565,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+@@ -1727,6 +1728,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
}
return 0;
}
@@ -621,7 +684,7 @@ index 182bc41..c88e101 100644
static void cleanup_group_ids(struct mount *mnt, struct mount *end)
{
diff --git a/fs/notify/group.c b/fs/notify/group.c
-index ad19959..adf290d 100644
+index d16b62c..06ca6bc 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -22,6 +22,7 @@
@@ -657,7 +720,7 @@ index ad19959..adf290d 100644
int fsnotify_fasync(int fd, struct file *file, int on)
{
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
-index d90deaa..60b4239 100644
+index 34c38fa..d40cf58 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -109,6 +109,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
@@ -676,7 +739,7 @@ index d90deaa..60b4239 100644
void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
{
-@@ -275,6 +277,7 @@ err:
+@@ -311,6 +313,7 @@ err:
return ret;
}
@@ -684,7 +747,7 @@ index d90deaa..60b4239 100644
int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group,
struct inode *inode, struct vfsmount *mnt, int allow_dups)
-@@ -336,6 +339,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
+@@ -372,6 +375,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
atomic_set(&mark->refcnt, 1);
mark->free_mark = free_mark;
}
@@ -693,7 +756,7 @@ index d90deaa..60b4239 100644
static int fsnotify_mark_destroy(void *ignored)
{
diff --git a/fs/open.c b/fs/open.c
-index d6fd3ac..5e99d8b 100644
+index de92c13..65d8ab0 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -62,6 +62,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
@@ -713,7 +776,7 @@ index d6fd3ac..5e99d8b 100644
SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
{
diff --git a/fs/splice.c b/fs/splice.c
-index 9ba380c..3419932 100644
+index 619359a..c14f60e 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1127,6 +1127,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
@@ -732,11 +795,23 @@ index 9ba380c..3419932 100644
/**
* splice_direct_to_actor - splices data directly between two non-pipes
+diff --git a/fs/xattr.c b/fs/xattr.c
+index 64e83ef..bd71e53 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -207,6 +207,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
+ *xattr_value = value;
+ return error;
+ }
++EXPORT_SYMBOL(vfs_getxattr_alloc);
+
+ /* Compare an extended attribute value with the given value */
+ int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
diff --git a/security/commoncap.c b/security/commoncap.c
-index b9d613e..ba3b618 100644
+index bab0611..3fa2f82 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
-@@ -988,9 +988,11 @@ int cap_mmap_addr(unsigned long addr)
+@@ -979,9 +979,11 @@ int cap_mmap_addr(unsigned long addr)
}
return ret;
}
@@ -749,7 +824,7 @@ index b9d613e..ba3b618 100644
}
+EXPORT_SYMBOL(cap_mmap_file);
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
-index d9d69e6..3f6f471 100644
+index 188c1d2..426d9af 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -7,6 +7,7 @@
@@ -769,7 +844,7 @@ index d9d69e6..3f6f471 100644
int devcgroup_inode_mknod(int mode, dev_t dev)
{
diff --git a/security/security.c b/security/security.c
-index 31614e9..b223a66 100644
+index 18b35c6..12c67af 100644
--- a/security/security.c
+++ b/security/security.c
@@ -407,6 +407,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
@@ -854,7 +929,7 @@ index 31614e9..b223a66 100644
{
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 2014-01-30 21:10:02.794146538 +0100
++++ linux/Documentation/ABI/testing/debugfs-aufs 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,50 @@
+What: /debug/aufs/si_<id>/
+Date: March 2009
@@ -908,7 +983,7 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Document
+ will be empty. About XINO files, see the aufs manual.
diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/ABI/testing/sysfs-aufs 2014-01-30 21:10:02.794146538 +0100
++++ linux/Documentation/ABI/testing/sysfs-aufs 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,31 @@
+What: /sys/fs/aufs/si_<id>/
+Date: March 2009
@@ -943,7 +1018,7 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentat
+ will be empty. About XINO files, see the aufs manual.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2014-01-30 21:10:02.807480310 +0100
++++ linux/Documentation/filesystems/aufs/design/01intro.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,161 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1108,7 +1183,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt lin
+about it. But currently I have implemented it in kernel space.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2014-08-14 10:15:45.115275734 +0200
++++ linux/Documentation/filesystems/aufs/design/02struct.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,251 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1363,7 +1438,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt li
+For this purpose, use "aumvdown" command in aufs-util.git.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2014-08-14 10:15:45.118609182 +0200
++++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,133 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1500,7 +1575,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt li
+ by over-mounting something (or another method).
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2014-01-30 21:10:02.807480310 +0100
++++ linux/Documentation/filesystems/aufs/design/04branch.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,75 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1579,7 +1654,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt li
+ same named entry on the upper branch.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2014-01-30 21:10:02.807480310 +0100
++++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,64 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1647,7 +1722,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.tx
+ copyup policy.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linux/Documentation/filesystems/aufs/design/06fhsm.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2014-08-14 10:15:45.118609182 +0200
++++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,120 @@
+
+# Copyright (C) 2011-2014 Junjiro R. Okajima
@@ -1771,7 +1846,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linu
+should restore the original file state after an error happens.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2014-01-30 21:10:02.807480310 +0100
++++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,46 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1819,9 +1894,109 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linu
+generic_file_mmap() and handles struct vm_operations_struct. In this
+approach, aufs met a hard problem and I could not solve it without
+switching the approach.
+diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt linux/Documentation/filesystems/aufs/design/06xattr.txt
+--- /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2015-01-25 13:00:38.627713742 +0100
+@@ -0,0 +1,96 @@
++
++# Copyright (C) 2014 Junjiro R. Okajima
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; 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
++
++
++Listing XATTR/EA and getting the value
++----------------------------------------------------------------------
++For the inode standard attributes (owner, group, timestamps, etc.), aufs
++shows the values from the topmost existing file. This behaviour is good
++for the non-dir entreis since the bahaviour exactly matches the shown
++information. But for the directories, aufs considers all the same named
++entries on the lower branches. Which means, if one of the lower entry
++rejects readdir call, then aufs returns an error even if the topmost
++entry allows it. This behaviour is necessary to respect the branch fs's
++security, but can make users confused since the user-visible standard
++attributes don't match the behaviour.
++To address this issue, aufs has a mount option called dirperm1 which
++checks the permission for the topmost entry only, and ignores the lower
++entry's permission.
++
++A similar issue can happen around XATTR.
++getxattr(2) and listxattr(2) families behave as if dirperm1 option is
++always set. Otherwise these very unpleasant situation can happen.
++- listxattr(2) may return the duplicated entires.
++- users may not be able to remove or reset the XATTR forever,
++
++
++XATTR/EA support in the internal (copy,move)-(up,down)
++----------------------------------------------------------------------
++Generally the extended attributes of inode are categorazied as these.
++- "security" for LSM and capability.
++- "system" for posix ACL, 'acl' mount option is required for the branch
++ fs generally.
++- "trusted" for userspace, CAP_SYS_ADMIN is required.
++- "user" for userspace, 'user_xattr' mount option is required for the
++ branch fs generally.
++
++Moreover there are some other categories. Aufs handles these rather
++unpopular categories as the ordinary ones, ie. there is no special
++condition nor exception.
++
++In copy-up, the support for XATTR on the dst branch may differ from the
++src branch. In this case, the copy-up operation will get an error and
++the original user operation which triggered the copy-up fails. It can
++happen that even all copy-up will fail.
++When both of src and dst branches support XATTR and if an error occurs
++during copying XATTR, then the copy-up should fail obviously. That is a
++good reason and aufs should return an error to userspace. But when only
++the src branch support XATTR, aufs should not return an error.
++For example, the src branch supports ACL but the dst branch doesn't
++because the dst branch may natively un-support it or temporary
++un-support it due to "noacl" mount option. Of course, the dst branch fs
++may NOT return an error even if the XATTR is not supported. It is
++totally up to the branch fs.
++
++Anyway when the aufs internal copy-up gets an error from the dst branch
++fs, then aufs tries removing the just copied entry and returns the error
++to the userspace. The worst case of this situation will be all copy-up
++will fail.
++
++For the copy-up operation, there two basic approaches.
++- copy the specified XATTR only (by category above), and return the
++ error if it happens inconditionally.
++- copy all XATTR, and ignore the error on the specified category only.
++
++In order to support XATTR and to implement the correct behaviour, aufs
++chooses the latter approach and introduces some attributes for its
++branch, "icexsec", "icexsys", "icextr", "icexusr", and "icexoth".
++They correspond to the XATTR namespaces (see above). Additionally, to be
++convenient, "icex" is also provided which means all "ix*" attributes are
++set.
++
++The meaning of these attributes is to ignore the error from setting
++XATTR on that branch.
++Note that aufs tries copying all XATTR unconditionally, and ignores the
++error from the dst branch according to the specified attributes.
++
++Some XATTR may have its default value. The default value may come from
++the parent dir or the environment. If the default value is set at the
++file creating-time, it will be overwritten by copy-up.
++Some contradiction may happen I am afraid.
++Do we need another attribute to stop copying XATTR? I am unsure. For
++now, aufs implements the branch attributes to ignore the error.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/07export.txt 2014-01-30 21:10:02.807480310 +0100
++++ linux/Documentation/filesystems/aufs/design/07export.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,58 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1883,7 +2058,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt li
+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2014-01-30 21:10:02.807480310 +0100
++++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,52 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -1939,7 +2114,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linu
+initramfs will use it to replace the old one at the next boot.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2014-01-30 21:10:02.807480310 +0100
++++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,46 @@
+
+# Copyright (C) 2010-2014 Junjiro R. Okajima
@@ -1989,7 +2164,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt lin
+vm_operations_struct for regular files only.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt linux/Documentation/filesystems/aufs/design/99plan.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/99plan.txt 2014-08-14 10:15:45.118609182 +0200
++++ linux/Documentation/filesystems/aufs/design/99plan.txt 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,58 @@
+
+# Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -2051,7 +2226,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt linu
+Otherwise from /new.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/README 2014-08-14 10:15:45.115275734 +0200
++++ linux/Documentation/filesystems/aufs/README 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,370 @@
+
+Aufs3 -- advanced multi layered unification filesystem version 3.x
@@ -2425,7 +2600,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta
+# End: ;
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 2014-01-30 21:10:02.827480967 +0100
++++ linux/fs/aufs/aufs.h 2015-01-25 13:00:38.627713742 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -2488,8 +2663,8 @@ diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
+#endif /* __AUFS_H__ */
diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/branch.c 2014-08-14 10:16:04.512608923 +0200
-@@ -0,0 +1,1447 @@
++++ linux/fs/aufs/branch.c 2015-01-25 13:00:38.627713742 +0100
+@@ -0,0 +1,1410 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -2518,34 +2693,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+/*
+ * free a single branch
+ */
-+
-+/* prohibit rmdir to the root of the branch */
-+/* todo: another new flag? */
-+static void au_br_dflags_force(struct au_branch *br)
-+{
-+ struct dentry *h_dentry;
-+
-+ h_dentry = au_br_dentry(br);
-+ spin_lock(&h_dentry->d_lock);
-+ br->br_dflags = h_dentry->d_flags & DCACHE_MOUNTED;
-+ h_dentry->d_flags |= DCACHE_MOUNTED;
-+ spin_unlock(&h_dentry->d_lock);
-+}
-+
-+/* restore its d_flags */
-+static void au_br_dflags_restore(struct au_branch *br)
-+{
-+ struct dentry *h_dentry;
-+
-+ if (br->br_dflags)
-+ return;
-+
-+ h_dentry = au_br_dentry(br);
-+ spin_lock(&h_dentry->d_lock);
-+ h_dentry->d_flags &= ~DCACHE_MOUNTED;
-+ spin_unlock(&h_dentry->d_lock);
-+}
-+
+static void au_br_do_free(struct au_branch *br)
+{
+ int i;
@@ -2580,8 +2727,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ else
+ break;
+
-+ au_br_dflags_restore(br);
-+
+ /* recursive lock, s_umount of branch's */
+ lockdep_off();
+ path_put(&br->br_path);
@@ -2768,6 +2913,12 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ goto out;
+ }
+
++ if (unlikely(inode->i_sb->s_stack_depth)) {
++ pr_err("already stacked, %s (%s)\n",
++ add->pathname, au_sbtype(inode->i_sb));
++ goto out;
++ }
++
+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
+ if (unlikely(err))
+ goto out;
@@ -2885,7 +3036,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ return err;
+}
+
-+/* intialize a new branch */
++/* initialize a new branch */
+static int au_br_init(struct au_branch *br, struct super_block *sb,
+ struct au_opt_add *add)
+{
@@ -2895,9 +3046,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ memset(&br->br_xino, 0, sizeof(br->br_xino));
+ mutex_init(&br->br_xino.xi_nondir_mtx);
+ br->br_perm = add->perm;
-+ BUILD_BUG_ON(sizeof(br->br_dflags)
-+ != sizeof(br->br_path.dentry->d_flags));
-+ br->br_dflags = DCACHE_MOUNTED;
+ br->br_path = add->path; /* set first, path_get() later */
+ spin_lock_init(&br->br_dykey_lock);
+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
@@ -2985,8 +3133,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ struct inode *root_inode;
+ aufs_bindex_t bend, amount;
+
-+ au_br_dflags_force(br);
-+
+ root = sb->s_root;
+ root_inode = root->d_inode;
+ bend = au_sbend(sb);
@@ -3161,7 +3307,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ ndentry = dpage->ndentry;
+ for (j = 0; !err && j < ndentry; j++) {
+ d = dpage->dentries[j];
-+ AuDebugOn(!d_count(d));
++ AuDebugOn(au_dcount(d) <= 0);
+ if (!au_digen_test(d, sigen)) {
+ di_read_lock_child(d, AuLock_IR);
+ if (unlikely(au_dbrange_test(d))) {
@@ -3281,14 +3427,21 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ struct file **to_free, int *idx)
+{
+ int err;
-+ unsigned char matched, unmatched;
++ unsigned char matched, root;
+ aufs_bindex_t bindex, bend;
+ struct au_fidir *fidir;
+ struct au_hfile *hfile;
+
+ err = 0;
++ root = IS_ROOT(file->f_dentry);
++ if (root) {
++ get_file(file);
++ to_free[*idx] = file;
++ (*idx)++;
++ goto out;
++ }
++
+ matched = 0;
-+ unmatched = 0;
+ fidir = au_fi(file)->fi_hdir;
+ AuDebugOn(!fidir);
+ bend = au_fbend_dir(file);
@@ -3297,21 +3450,12 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ if (!hfile->hf_file)
+ continue;
+
-+ if (hfile->hf_br->br_id == br_id)
++ if (hfile->hf_br->br_id == br_id) {
+ matched = 1;
-+ else
-+ unmatched = 1;
-+ if (matched && unmatched)
+ break;
++ }
+ }
-+ if (!matched)
-+ goto out; /* success */
-+
-+ if (unmatched) {
-+ get_file(file);
-+ to_free[*idx] = file;
-+ (*idx)++;
-+ } else
++ if (matched)
+ err = -EBUSY;
+
+out:
@@ -3903,12 +4047,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ /* non-fhsm --> fhsm */
+ br->br_fhsm = bf;
+
-+ if ((br->br_perm & AuBrAttr_UNPIN)
-+ && !(mod->perm & AuBrAttr_UNPIN))
-+ au_br_dflags_force(br);
-+ else if (!(br->br_perm & AuBrAttr_UNPIN)
-+ && (mod->perm & AuBrAttr_UNPIN))
-+ au_br_dflags_restore(br);
+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
+ br->br_perm = mod->perm;
+ goto out; /* success */
@@ -3939,8 +4077,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+}
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 2014-08-14 10:15:45.118609182 +0200
-@@ -0,0 +1,268 @@
++++ linux/fs/aufs/branch.h 2015-01-25 13:00:38.627713742 +0100
+@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -4039,7 +4177,6 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+ aufs_bindex_t br_id;
+
+ int br_perm;
-+ unsigned int br_dflags;
+ struct path br_path;
+ spinlock_t br_dykey_lock;
+ struct au_dykey *br_dykey[AuBrDynOp];
@@ -4211,8 +4348,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+#endif /* __AUFS_BRANCH_H__ */
diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/conf.mk 2014-08-14 10:15:45.118609182 +0200
-@@ -0,0 +1,37 @@
++++ linux/fs/aufs/conf.mk 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,38 @@
+
+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
+
@@ -4226,6 +4363,7 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
+ SBILIST \
+ HNOTIFY HFSNOTIFY \
+ EXPORT INO_T_64 \
++ XATTR \
+ FHSM \
+ RDU \
+ SHWH \
@@ -4252,8 +4390,8 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
+-include ${srctree}/${src}/conf_priv.mk
diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/cpup.c 2014-08-14 10:15:45.118609182 +0200
-@@ -0,0 +1,1301 @@
++++ linux/fs/aufs/cpup.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,1303 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -4421,15 +4559,17 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
+ struct au_cpup_reg_attr *h_src_attr)
+{
-+ int err, sbits;
++ int err, sbits, icex;
+ struct iattr ia;
+ struct path h_path;
+ struct inode *h_isrc, *h_idst;
+ struct kstat *h_st;
++ struct au_branch *br;
+
+ h_path.dentry = au_h_dptr(dst, bindex);
+ h_idst = h_path.dentry->d_inode;
-+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
++ br = au_sbr(dst->d_sb, bindex);
++ h_path.mnt = au_br_mnt(br);
+ h_isrc = h_src->d_inode;
+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
+ | ATTR_ATIME | ATTR_MTIME
@@ -4470,6 +4610,10 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
+ }
+
++ icex = br->br_perm & AuBrAttr_ICEX;
++ if (!err)
++ err = au_cpup_xattr(h_path.dentry, h_src, icex);
++
+ return err;
+}
+
@@ -5377,7 +5521,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+{
+ int err, wkq_err;
+ aufs_bindex_t bdst;
-+ struct dentry *dentry, *parent, *h_orph, *h_parent, *h_dentry;
++ struct dentry *dentry, *parent, *h_orph, *h_parent;
+ struct inode *dir, *h_dir, *h_tmpdir;
+ struct au_wbr *wbr;
+ struct au_pin wh_pin, *pin_orig;
@@ -5400,10 +5544,6 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ h_tmpdir = h_orph->d_inode;
+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
+
-+ if (file)
-+ h_dentry = au_hf_top(file)->f_dentry;
-+ else
-+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
+ /* todo: au_h_open_pre()? */
+
@@ -5557,7 +5697,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+}
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 2014-01-30 21:10:02.827480967 +0100
++++ linux/fs/aufs/cpup.h 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -5655,7 +5795,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
+#endif /* __AUFS_CPUP_H__ */
diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dbgaufs.c 2014-01-30 21:10:02.827480967 +0100
++++ linux/fs/aufs/dbgaufs.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -5990,7 +6130,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
+ int err;
+
+ /*
-+ * This function is a dynamic '__init' fucntion actually,
++ * This function is a dynamic '__init' function actually,
+ * so the tiny check for si_rwsem is unnecessary.
+ */
+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
@@ -6016,7 +6156,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
+{
+ /*
-+ * This function is a dynamic '__init' fucntion actually,
++ * This function is a dynamic '__init' function actually,
+ * so the tiny check for si_rwsem is unnecessary.
+ */
+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
@@ -6032,7 +6172,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
+ char name[SysaufsSiNameLen];
+
+ /*
-+ * This function is a dynamic '__init' fucntion actually,
++ * This function is a dynamic '__init' function actually,
+ * so the tiny check for si_rwsem is unnecessary.
+ */
+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
@@ -6091,7 +6231,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
+}
diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dbgaufs.h 2014-01-30 21:10:02.827480967 +0100
++++ linux/fs/aufs/dbgaufs.h 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -6143,8 +6283,8 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
+#endif /* __DBGAUFS_H__ */
diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dcsub.c 2014-01-30 21:10:02.827480967 +0100
-@@ -0,0 +1,243 @@
++++ linux/fs/aufs/dcsub.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -6244,7 +6384,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
+ dpages->ndpage++;
+ }
+
-+ AuDebugOn(!d_count(dentry));
++ AuDebugOn(au_dcount(dentry) <= 0);
+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
+ return 0; /* success */
+
@@ -6252,79 +6392,60 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
+ return err;
+}
+
-+/* try d_walk() in linux/fs/dcache.c */
-+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
-+ au_dpages_test test, void *arg)
-+{
++/* todo: BAD approach */
++/* copied from linux/fs/dcache.c */
++enum d_walk_ret {
++ D_WALK_CONTINUE,
++ D_WALK_QUIT,
++ D_WALK_NORETRY,
++ D_WALK_SKIP,
++};
++
++extern void d_walk(struct dentry *parent, void *data,
++ enum d_walk_ret (*enter)(void *, struct dentry *),
++ void (*finish)(void *));
++
++struct ac_dpages_arg {
+ int err;
-+ struct dentry *this_parent;
-+ struct list_head *next;
-+ struct super_block *sb = root->d_sb;
++ struct au_dcsub_pages *dpages;
++ struct super_block *sb;
++ au_dpages_test test;
++ void *arg;
++};
+
-+ err = 0;
-+ write_seqlock(&rename_lock);
-+ this_parent = root;
-+ spin_lock(&this_parent->d_lock);
-+repeat:
-+ next = this_parent->d_subdirs.next;
-+resume:
-+ if (this_parent->d_sb == sb
-+ && !IS_ROOT(this_parent)
-+ && au_di(this_parent)
-+ && d_count(this_parent)
-+ && (!test || test(this_parent, arg))) {
-+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
-+ if (unlikely(err))
-+ goto out;
-+ }
++static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry)
++{
++ enum d_walk_ret ret;
++ struct ac_dpages_arg *arg = _arg;
+
-+ while (next != &this_parent->d_subdirs) {
-+ struct list_head *tmp = next;
-+ struct dentry *dentry = list_entry(tmp, struct dentry,
-+ d_u.d_child);
-+
-+ next = tmp->next;
-+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-+ if (d_count(dentry)) {
-+ if (!list_empty(&dentry->d_subdirs)) {
-+ spin_unlock(&this_parent->d_lock);
-+ spin_release(&dentry->d_lock.dep_map, 1,
-+ _RET_IP_);
-+ this_parent = dentry;
-+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
-+ _RET_IP_);
-+ goto repeat;
-+ }
-+ if (dentry->d_sb == sb
-+ && au_di(dentry)
-+ && (!test || test(dentry, arg)))
-+ err = au_dpages_append(dpages, dentry,
-+ GFP_ATOMIC);
-+ }
-+ spin_unlock(&dentry->d_lock);
-+ if (unlikely(err))
-+ goto out;
++ ret = D_WALK_CONTINUE;
++ if (dentry->d_sb == arg->sb
++ && !IS_ROOT(dentry)
++ && au_dcount(dentry) > 0
++ && au_di(dentry)
++ && (!arg->test || arg->test(dentry, arg->arg))) {
++ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC);
++ if (unlikely(arg->err))
++ ret = D_WALK_QUIT;
+ }
+
-+ if (this_parent != root) {
-+ struct dentry *tmp;
-+ struct dentry *child;
++ return ret;
++}
+
-+ tmp = this_parent->d_parent;
-+ rcu_read_lock();
-+ spin_unlock(&this_parent->d_lock);
-+ child = this_parent;
-+ this_parent = tmp;
-+ spin_lock(&this_parent->d_lock);
-+ rcu_read_unlock();
-+ next = child->d_u.d_child.next;
-+ goto resume;
-+ }
++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
++ au_dpages_test test, void *arg)
++{
++ struct ac_dpages_arg args = {
++ .err = 0,
++ .dpages = dpages,
++ .sb = root->d_sb,
++ .test = test,
++ .arg = arg
++ };
+
-+out:
-+ spin_unlock(&this_parent->d_lock);
-+ write_sequnlock(&rename_lock);
-+ return err;
++ d_walk(root, &args, au_call_dpages_append, NULL);
++
++ return args.err;
+}
+
+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
@@ -6336,7 +6457,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
+ write_seqlock(&rename_lock);
+ spin_lock(&dentry->d_lock);
+ if (do_include
-+ && d_count(dentry)
++ && au_dcount(dentry) > 0
+ && (!test || test(dentry, arg)))
+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
+ spin_unlock(&dentry->d_lock);
@@ -6350,7 +6471,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
+ while (!IS_ROOT(dentry)) {
+ dentry = dentry->d_parent; /* rename_lock is locked */
+ spin_lock(&dentry->d_lock);
-+ if (d_count(dentry)
++ if (au_dcount(dentry) > 0
+ && (!test || test(dentry, arg)))
+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
+ spin_unlock(&dentry->d_lock);
@@ -6390,8 +6511,8 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
+}
diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dcsub.h 2014-08-14 10:15:45.118609182 +0200
-@@ -0,0 +1,120 @@
++++ linux/fs/aufs/dcsub.h 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -6510,12 +6631,17 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
+ && !memcmp(a->name, b->name, a->len);
+}
+
++static inline int au_dcount(struct dentry *d)
++{
++ return (int)d_count(d);
++}
++
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DCSUB_H__ */
diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/debug.c 2014-08-14 10:15:45.121942630 +0200
-@@ -0,0 +1,519 @@
++++ linux/fs/aufs/debug.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -6574,6 +6700,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
+MODULE_PARM_DESC(debug, "debug print");
+module_param_named(debug, aufs_debug, atomic_t, S_IRUGO | S_IWUSR | S_IWGRP);
+
++DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */
+char *au_plevel = KERN_DEBUG;
+#define dpri(fmt, ...) do { \
+ if ((au_plevel \
@@ -6686,7 +6813,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
+ struct dentry *d;
+
+ spin_lock(&inode->i_lock);
-+ hlist_for_each_entry(d, &inode->i_dentry, d_alias)
++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias)
+ au_dpri_dentry(d);
+ spin_unlock(&inode->i_lock);
+}
@@ -6706,7 +6833,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n",
+ bindex, dentry, dentry,
+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
-+ d_count(dentry), dentry->d_flags,
++ au_dcount(dentry), dentry->d_flags,
+ d_unhashed(dentry) ? "un" : "");
+ hn = -1;
+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
@@ -7037,8 +7164,8 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
+}
diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/debug.h 2014-01-30 21:10:02.827480967 +0100
-@@ -0,0 +1,247 @@
++++ linux/fs/aufs/debug.h 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -7151,6 +7278,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
+struct au_finfo;
+struct dentry;
+#ifdef CONFIG_AUFS_DEBUG
++extern struct mutex au_dbg_mtx;
+extern char *au_plevel;
+struct au_nhash;
+void au_dpri_whlist(struct au_nhash *whlist);
@@ -7179,38 +7307,52 @@ diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
+int __init au_debug_init(void);
+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
+#define AuDbgWhlist(w) do { \
++ mutex_lock(&au_dbg_mtx); \
+ AuDbg(#w "\n"); \
+ au_dpri_whlist(w); \
++ mutex_unlock(&au_dbg_mtx); \
+} while (0)
+
+#define AuDbgVdir(v) do { \
++ mutex_lock(&au_dbg_mtx); \
+ AuDbg(#v "\n"); \
+ au_dpri_vdir(v); \
++ mutex_unlock(&au_dbg_mtx); \
+} while (0)
+
+#define AuDbgInode(i) do { \
++ mutex_lock(&au_dbg_mtx); \
+ AuDbg(#i "\n"); \
+ au_dpri_inode(i); \
++ mutex_unlock(&au_dbg_mtx); \
+} while (0)
+
+#define AuDbgDAlias(i) do { \
++ mutex_lock(&au_dbg_mtx); \
+ AuDbg(#i "\n"); \
+ au_dpri_dalias(i); \
++ mutex_unlock(&au_dbg_mtx); \
+} while (0)
+
+#define AuDbgDentry(d) do { \
++ mutex_lock(&au_dbg_mtx); \
+ AuDbg(#d "\n"); \
+ au_dpri_dentry(d); \
++ mutex_unlock(&au_dbg_mtx); \
+} while (0)
+
+#define AuDbgFile(f) do { \
++ mutex_lock(&au_dbg_mtx); \
+ AuDbg(#f "\n"); \
+ au_dpri_file(f); \
++ mutex_unlock(&au_dbg_mtx); \
+} while (0)
+
+#define AuDbgSb(sb) do { \
++ mutex_lock(&au_dbg_mtx); \
+ AuDbg(#sb "\n"); \
+ au_dpri_sb(sb); \
++ mutex_unlock(&au_dbg_mtx); \
+} while (0)
+
+#define AuDbgSleep(sec) do { \
@@ -7288,8 +7430,8 @@ diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
+#endif /* __AUFS_DEBUG_H__ */
diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dentry.c 2014-08-14 10:16:04.515942371 +0200
-@@ -0,0 +1,1094 @@
++++ linux/fs/aufs/dentry.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,1096 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -8296,10 +8438,6 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ if (unlikely(!au_di(dentry)))
+ goto out;
+
-+ inode = dentry->d_inode;
-+ if (inode && is_bad_inode(inode))
-+ goto out;
-+
+ valid = 1;
+ sb = dentry->d_sb;
+ /*
@@ -8313,6 +8451,12 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ AuTraceErr(err);
+ goto out;
+ }
++ inode = dentry->d_inode;
++ if (unlikely(inode && is_bad_inode(inode))) {
++ err = -EINVAL;
++ AuTraceErr(err);
++ goto out_dgrade;
++ }
+ if (unlikely(au_dbrange_test(dentry))) {
+ err = -EINVAL;
+ AuTraceErr(err);
@@ -8331,7 +8475,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ di_downgrade_lock(dentry, AuLock_IR);
+
+ err = -EINVAL;
-+ if (!(flags & LOOKUP_OPEN)
++ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY))
+ && inode
+ && !(inode->i_state && I_LINKABLE)
+ && (IS_DEADDIR(inode) || !inode->i_nlink))
@@ -8386,7 +8530,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+};
diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dentry.h 2014-08-14 10:15:45.121942630 +0200
++++ linux/fs/aufs/dentry.h 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -8623,7 +8767,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
+#endif /* __AUFS_DENTRY_H__ */
diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dinfo.c 2014-08-14 10:15:45.121942630 +0200
++++ linux/fs/aufs/dinfo.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -8945,7 +9089,7 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
+ return NULL;
+ AuDebugOn(bindex < 0);
+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
-+ AuDebugOn(d && d_count(d) <= 0);
++ AuDebugOn(d && au_dcount(d) <= 0);
+ return d;
+}
+
@@ -9171,7 +9315,7 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
+}
diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dir.c 2014-08-14 10:15:45.121942630 +0200
++++ linux/fs/aufs/dir.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -9820,8 +9964,8 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
+};
diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dir.h 2014-01-30 21:10:02.830814411 +0100
-@@ -0,0 +1,136 @@
++++ linux/fs/aufs/dir.h 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -9942,17 +10086,11 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
+ unsigned long arg);
+#endif
+#else
-+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ return -EINVAL;
-+}
++AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file,
++ unsigned int cmd, unsigned long arg)
+#ifdef CONFIG_COMPAT
-+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ return -EINVAL;
-+}
++AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file,
++ unsigned int cmd, unsigned long arg)
+#endif
+#endif
+
@@ -9960,7 +10098,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
+#endif /* __AUFS_DIR_H__ */
diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dynop.c 2014-01-30 21:10:02.830814411 +0100
++++ linux/fs/aufs/dynop.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2010-2014 Junjiro R. Okajima
@@ -10222,7 +10360,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
+/* ---------------------------------------------------------------------- */
+/*
+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
-+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
++ * This behaviour is necessary to return an error from open(O_DIRECT) instead
+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
+ * See the aufs manual in detail.
@@ -10343,7 +10481,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
+}
diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dynop.h 2014-01-30 21:10:02.830814411 +0100
++++ linux/fs/aufs/dynop.h 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010-2014 Junjiro R. Okajima
@@ -10422,7 +10560,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
+#endif /* __AUFS_DYNOP_H__ */
diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/export.c 2014-01-30 21:10:02.830814411 +0100
++++ linux/fs/aufs/export.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,831 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -10669,7 +10807,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
+ dentry = d_find_alias(inode);
+ else {
+ spin_lock(&inode->i_lock);
-+ hlist_for_each_entry(d, &inode->i_dentry, d_alias) {
++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
+ spin_lock(&d->d_lock);
+ if (!au_test_anon(d)
+ && d->d_parent->d_inode->i_ino == dir_ino) {
@@ -11140,7 +11278,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
+ ii_read_lock_child(inode);
+ bindex = au_ibstart(inode);
+ if (!dir) {
-+ dentry = d_find_alias(inode);
++ dentry = d_find_any_alias(inode);
+ if (unlikely(!dentry))
+ goto out_unlock;
+ AuDebugOn(au_test_anon(dentry));
@@ -11156,7 +11294,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
+ ii_read_unlock(dir);
+ if (unlikely(!h_dir))
+ goto out_parent;
-+ h_parent = d_find_alias(h_dir);
++ h_parent = d_find_any_alias(h_dir);
+ if (unlikely(!h_parent))
+ goto out_hparent;
+
@@ -11257,8 +11395,8 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
+}
diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
--- /usr/share/empty/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/fhsm.c 2014-08-14 10:15:45.121942630 +0200
-@@ -0,0 +1,410 @@
++++ linux/fs/aufs/fhsm.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2011-2014 Junjiro R. Okajima
+ *
@@ -11287,6 +11425,34 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+#include <linux/statfs.h>
+#include "aufs.h"
+
++static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
++{
++ struct au_sbinfo *sbinfo;
++ struct au_fhsm *fhsm;
++
++ SiMustAnyLock(sb);
++
++ sbinfo = au_sbi(sb);
++ fhsm = &sbinfo->si_fhsm;
++ AuDebugOn(!fhsm);
++ return fhsm->fhsm_bottom;
++}
++
++void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
++{
++ struct au_sbinfo *sbinfo;
++ struct au_fhsm *fhsm;
++
++ SiMustWriteLock(sb);
++
++ sbinfo = au_sbi(sb);
++ fhsm = &sbinfo->si_fhsm;
++ AuDebugOn(!fhsm);
++ fhsm->fhsm_bottom = bindex;
++}
++
++/* ---------------------------------------------------------------------- */
++
+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
+{
+ struct au_br_fhsm *bf;
@@ -11360,8 +11526,6 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
+{
+ int err;
-+ unsigned char do_notify;
-+ aufs_bindex_t bend, blower;
+ struct au_sbinfo *sbinfo;
+ struct au_fhsm *fhsm;
+ struct au_branch *br;
@@ -11372,19 +11536,8 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+
+ sbinfo = au_sbi(sb);
+ fhsm = &sbinfo->si_fhsm;
-+ if (!au_ftest_si(sbinfo, FHSM))
-+ return;
-+
-+ do_notify = 0;
-+ bend = au_sbend(sb);
-+ for (blower = bindex + 1; blower <= bend; blower++) {
-+ br = au_sbr(sb, blower);
-+ if (au_br_fhsm(br->br_perm)) {
-+ do_notify = 1;
-+ break;
-+ }
-+ }
-+ if (!do_notify)
++ if (!au_ftest_si(sbinfo, FHSM)
++ || fhsm->fhsm_bottom == bindex)
+ return;
+
+ br = au_sbr(sb, bindex);
@@ -11405,7 +11558,7 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+ struct au_branch *br;
+
+ /* exclude the bottom */
-+ bend = au_sbend(sb);
++ bend = au_fhsm_bottom(sb);
+ for (bindex = 0; bindex < bend; bindex++) {
+ br = au_sbr(sb, bindex);
+ if (au_br_fhsm(br->br_perm))
@@ -11459,7 +11612,7 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+ /* except the bottom branch */
+ err = 0;
+ nstbr = 0;
-+ bend = au_sbend(sb);
++ bend = au_fhsm_bottom(sb);
+ for (bindex = 0; !err && bindex < bend; bindex++) {
+ br = au_sbr(sb, bindex);
+ if (!au_br_fhsm(br->br_perm))
@@ -11522,7 +11675,7 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+ AuDebugOn(!sb);
+ /* exclude the bottom branch */
+ nfhsm = 0;
-+ bend = au_sbend(sb);
++ bend = au_fhsm_bottom(sb);
+ for (bindex = 0; bindex < bend; bindex++) {
+ br = au_sbr(sb, bindex);
+ if (au_br_fhsm(br->br_perm))
@@ -11650,6 +11803,7 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+ atomic_set(&fhsm->fhsm_readable, 0);
+ fhsm->fhsm_expire
+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
++ fhsm->fhsm_bottom = -1;
+}
+
+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
@@ -11671,8 +11825,8 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
+}
diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/file.c 2014-08-14 10:16:04.515942371 +0200
-@@ -0,0 +1,835 @@
++++ linux/fs/aufs/file.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,829 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -12062,7 +12216,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+{
+ int err;
+ aufs_bindex_t dbstart;
-+ struct dentry *parent, *h_dentry;
++ struct dentry *parent;
+ struct inode *inode;
+ struct super_block *sb;
+ struct file *h_file;
@@ -12105,13 +12259,9 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+ if (unlikely(err))
+ goto out_dgrade;
+
-+ h_dentry = au_hf_top(file)->f_dentry;
+ dbstart = au_dbstart(cpg.dentry);
-+ if (dbstart <= cpg.bdst) {
-+ h_dentry = au_h_dptr(cpg.dentry, cpg.bdst);
-+ AuDebugOn(!h_dentry);
++ if (dbstart <= cpg.bdst)
+ cpg.bsrc = cpg.bdst;
-+ }
+
+ if (dbstart <= cpg.bdst /* just reopen */
+ || !d_unhashed(cpg.dentry) /* copyup and reopen */
@@ -12297,8 +12447,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+ if (p->hf_file) {
+ if (file_inode(p->hf_file))
+ break;
-+ else
-+ au_hfput(p, file);
++ au_hfput(p, file);
+ }
+ } else {
+ bend = au_br_index(sb, brid);
@@ -12315,8 +12464,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+ if (p->hf_file) {
+ if (file_inode(p->hf_file))
+ break;
-+ else
-+ au_hfput(p, file);
++ au_hfput(p, file);
+ }
+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
+}
@@ -12510,8 +12658,8 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
+};
diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/file.h 2014-08-14 10:15:45.121942630 +0200
-@@ -0,0 +1,289 @@
++++ linux/fs/aufs/file.h 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -12609,13 +12757,8 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
+ struct file *h_file);
+#else
-+static inline
-+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
-+ int force_wr)
-+{
-+ return NULL;
-+}
-+
++AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
++ aufs_bindex_t bindex, int force_wr)
+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
+ struct file *h_file);
+#endif
@@ -12803,7 +12946,7 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
+#endif /* __AUFS_FILE_H__ */
diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/finfo.c 2014-01-30 21:10:02.850815069 +0100
++++ linux/fs/aufs/finfo.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -12963,7 +13106,7 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
+}
diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/f_op.c 2014-08-14 10:16:04.515942371 +0200
++++ linux/fs/aufs/f_op.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -13177,7 +13320,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
+ bstart = au_fbstart(file);
+ h_file = au_hf_top(file);
+ get_file(h_file);
-+ h_inode = h_file->f_dentry->d_inode;
++ h_inode = file_inode(h_file);
+ blks = h_inode->i_blocks;
+ au_unpin(&pin);
+ di_read_unlock(dentry, AuLock_IR);
@@ -13306,7 +13449,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
+ bstart = au_fbstart(file);
+ h_file = au_hf_top(file);
+ get_file(h_file);
-+ h_inode = h_file->f_dentry->d_inode;
++ h_inode = file_inode(h_file);
+ blks = h_inode->i_blocks;
+ au_unpin(&pin);
+ di_read_unlock(dentry, AuLock_IR);
@@ -13402,7 +13545,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
+ bstart = au_fbstart(file);
+ h_file = au_hf_top(file);
+ get_file(h_file);
-+ h_inode = h_file->f_dentry->d_inode;
++ h_inode = file_inode(h_file);
+ blks = h_inode->i_blocks;
+ au_unpin(&pin);
+ di_read_unlock(dentry, AuLock_IR);
@@ -13780,7 +13923,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
+};
diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/fstype.h 2014-01-30 21:10:02.850815069 +0100
++++ linux/fs/aufs/fstype.h 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -14253,8 +14396,8 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
+#endif /* __AUFS_FSTYPE_H__ */
diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/hfsnotify.c 2014-08-14 10:16:04.515942371 +0200
-@@ -0,0 +1,281 @@
++++ linux/fs/aufs/hfsnotify.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -14317,10 +14460,12 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
+ * by udba rename or rmdir, aufs assign a new inode to the known
+ * h_inode, so specify 1 to allow dups.
+ */
++ lockdep_off();
+ err = fsnotify_add_mark(mark, br->br_hfsn->hfsn_group, hinode->hi_inode,
+ /*mnt*/NULL, /*allow_dups*/1);
+ /* even if err */
+ fsnotify_put_mark(mark);
++ lockdep_on();
+
+ return err;
+}
@@ -14339,8 +14484,10 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
+ group = mark->group;
+ fsnotify_get_group(group);
+ spin_unlock(&mark->lock);
++ lockdep_off();
+ fsnotify_destroy_mark(mark, group);
+ fsnotify_put_group(group);
++ lockdep_on();
+
+ /* free hn by myself */
+ return 0;
@@ -14467,8 +14614,11 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
+ struct au_br_hfsnotify *hfsn;
+
+ hfsn = br->br_hfsn;
-+ if (hfsn)
++ if (hfsn) {
++ lockdep_off();
+ fsnotify_put_group(hfsn->hfsn_group);
++ lockdep_on();
++ }
+}
+
+static int au_hfsn_init_br(struct au_branch *br, int perm)
@@ -14538,7 +14688,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
+};
diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/hfsplus.c 2014-01-30 21:10:02.850815069 +0100
++++ linux/fs/aufs/hfsplus.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010-2014 Junjiro R. Okajima
@@ -14598,7 +14748,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
+}
diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/hnotify.c 2014-08-14 10:16:04.515942371 +0200
++++ linux/fs/aufs/hnotify.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,714 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -14813,7 +14963,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
+ AuDebugOn(!name);
+ au_iigen_dec(inode);
+ spin_lock(&inode->i_lock);
-+ hlist_for_each_entry(d, &inode->i_dentry, d_alias) {
++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
+ spin_lock(&d->d_lock);
+ dname = &d->d_name;
+ if (dname->len != nlen
@@ -14829,7 +14979,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
+ spin_unlock(&inode->i_lock);
+ } else {
+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
-+ d = d_find_alias(inode);
++ d = d_find_any_alias(inode);
+ if (!d) {
+ au_iigen_dec(inode);
+ goto out;
@@ -14974,13 +15124,13 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
+ struct dentry *dentry, *d, *parent;
+ struct qstr *dname;
+
-+ parent = d_find_alias(dir);
++ parent = d_find_any_alias(dir);
+ if (!parent)
+ return NULL;
+
+ dentry = NULL;
+ spin_lock(&parent->d_lock);
-+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
++ list_for_each_entry(d, &parent->d_subdirs, d_child) {
+ /* AuDbg("%pd\n", d); */
+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
+ dname = &d->d_name;
@@ -14990,7 +15140,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
+ au_digen_dec(d);
+ else
+ goto cont_unlock;
-+ if (d_count(d)) {
++ if (au_dcount(d) > 0) {
+ dentry = dget_dlock(d);
+ spin_unlock(&d->d_lock);
+ break;
@@ -15316,7 +15466,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
+}
diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/iinfo.c 2014-08-14 10:15:45.128609525 +0200
++++ linux/fs/aufs/iinfo.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -15597,8 +15747,8 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
+}
diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/inode.c 2014-08-14 10:15:45.128609525 +0200
-@@ -0,0 +1,492 @@
++++ linux/fs/aufs/inode.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -15839,6 +15989,10 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
+ au_igrab(h_dentry->d_inode), flags);
+ }
+ au_cpup_attr_all(inode, /*force*/1);
++ /*
++ * to force calling aufs_get_acl() every time,
++ * do not call cache_no_acl() for aufs inode.
++ */
+
+out:
+ return err;
@@ -16093,8 +16247,8 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
+}
diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/inode.h 2014-08-14 10:15:45.128609525 +0200
-@@ -0,0 +1,601 @@
++++ linux/fs/aufs/inode.h 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -16205,6 +16359,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
+};
+
+void au_pin_hdir_unlock(struct au_pin *p);
++int au_pin_hdir_lock(struct au_pin *p);
+int au_pin_hdir_relock(struct au_pin *p);
+void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task);
+void au_pin_hdir_acquire_nest(struct au_pin *p);
@@ -16275,6 +16430,29 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
+ unsigned int udba, unsigned char flags) __must_check;
+int au_do_pin(struct au_pin *pin) __must_check;
+void au_unpin(struct au_pin *pin);
++int au_reval_for_attr(struct dentry *dentry, unsigned int sigen);
++
++#define AuIcpup_DID_CPUP 1
++#define au_ftest_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;
++ unsigned char pin_flags;
++ aufs_bindex_t btgt;
++ unsigned int udba;
++ struct au_pin pin;
++ struct path h_path;
++ struct inode *h_inode;
++};
++
++int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
++ struct au_icpup_args *a);
++
++int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path);
+
+/* i_op_add.c */
+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
@@ -16365,6 +16543,56 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
+#endif /* CONFIG_PROC_FS */
+
++#ifdef CONFIG_AUFS_XATTR
++/* xattr.c */
++int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags);
++ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
++ssize_t aufs_getxattr(struct dentry *dentry, const char *name, void *value,
++ size_t size);
++int aufs_setxattr(struct dentry *dentry, const char *name, const void *value,
++ size_t size, int flags);
++int aufs_removexattr(struct dentry *dentry, const char *name);
++
++/* void au_xattr_init(struct super_block *sb); */
++#else
++AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src,
++ int ignore_flags);
++/* AuStubVoid(au_xattr_init, struct super_block *sb); */
++#endif
++
++#ifdef CONFIG_FS_POSIX_ACL
++struct posix_acl *aufs_get_acl(struct inode *inode, int type);
++int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
++#endif
++
++#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
++enum {
++ AU_XATTR_SET,
++ AU_XATTR_REMOVE,
++ AU_ACL_SET
++};
++
++struct au_srxattr {
++ int type;
++ union {
++ struct {
++ const char *name;
++ const void *value;
++ size_t size;
++ int flags;
++ } set;
++ struct {
++ const char *name;
++ } remove;
++ struct {
++ struct posix_acl *acl;
++ int type;
++ } acl_set;
++ } u;
++};
++ssize_t au_srxattr(struct dentry *dentry, struct au_srxattr *arg);
++#endif
++
+/* ---------------------------------------------------------------------- */
+
+/* lock subclass for iinfo */
@@ -16637,18 +16865,10 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
+}
+
+#else
-+static inline
-+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
-+ struct inode *inode __maybe_unused)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
-+{
-+ return NULL;
-+}
-+
++AuStub(int, au_hn_alloc, return -EOPNOTSUPP,
++ struct au_hinode *hinode __maybe_unused,
++ struct inode *inode __maybe_unused)
++AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode)
+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
+ int do_set __maybe_unused)
@@ -16698,8 +16918,8 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
+#endif /* __AUFS_INODE_H__ */
diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/ioctl.c 2014-08-14 10:15:45.128609525 +0200
-@@ -0,0 +1,214 @@
++++ linux/fs/aufs/ioctl.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -16824,6 +17044,7 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long err;
++ struct dentry *dentry;
+
+ switch (cmd) {
+ case AUFS_CTL_RDU:
@@ -16844,7 +17065,11 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
+ break;
+
+ case AUFS_CTL_FHSM_FD:
-+ err = au_fhsm_fd(file->f_dentry->d_sb, arg);
++ dentry = file->f_dentry;
++ if (IS_ROOT(dentry))
++ err = au_fhsm_fd(dentry->d_sb, arg);
++ else
++ err = -ENOTTY;
+ break;
+
+ default:
@@ -16916,8 +17141,8 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
+#endif
diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/i_op_add.c 2014-08-14 10:15:45.121942630 +0200
-@@ -0,0 +1,885 @@
++++ linux/fs/aufs/i_op_add.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -17462,7 +17687,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+ dget(au_h_dptr(src_dentry, a->bsrc)));
+ dget(a->h_path.dentry);
+ au_set_h_dptr(dentry, a->bdst, NULL);
++ AuDbg("temporary d_inode...\n");
++ spin_lock(&dentry->d_lock);
+ dentry->d_inode = src_dentry->d_inode; /* tmp */
++ spin_unlock(&dentry->d_lock);
+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
+ if (IS_ERR(h_file))
+ err = PTR_ERR(h_file);
@@ -17484,7 +17712,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+ au_set_h_dptr(dentry, a->bdst,
+ a->h_path.dentry);
+ }
++ spin_lock(&dentry->d_lock);
+ dentry->d_inode = NULL; /* restore */
++ spin_unlock(&dentry->d_lock);
++ AuDbg("temporary d_inode...done\n");
+ au_set_h_dptr(dentry, a->bsrc, NULL);
+ au_set_dbend(dentry, bend);
+ } else {
@@ -17805,8 +18036,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
+}
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 2014-08-14 10:15:45.121942630 +0200
-@@ -0,0 +1,1142 @@
++++ linux/fs/aufs/i_op.c 2015-01-25 13:00:38.631047076 +0100
+@@ -0,0 +1,1306 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -18012,14 +18243,25 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+
+ if (npositive) {
+ inode = au_new_inode(dentry, /*must_new*/0);
-+ ret = (void *)inode;
-+ }
-+ if (IS_ERR(inode)) {
-+ inode = NULL;
-+ goto out_unlock;
++ if (IS_ERR(inode)) {
++ ret = (void *)inode;
++ inode = NULL;
++ goto out_unlock;
++ }
+ }
+
++ if (inode)
++ atomic_inc(&inode->i_count);
+ ret = d_splice_alias(inode, dentry);
++ if (IS_ERR(ret)
++ && PTR_ERR(ret) == -EIO
++ && inode
++ && S_ISDIR(inode->i_mode)) {
++ atomic_inc(&inode->i_count);
++ ret = d_materialise_unique(dentry, inode);
++ if (!IS_ERR(ret))
++ ii_write_unlock(inode);
++ }
+#if 0
+ if (unlikely(d_need_lookup(dentry))) {
+ spin_lock(&dentry->d_lock);
@@ -18027,10 +18269,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ spin_unlock(&dentry->d_lock);
+ } else
+#endif
-+ if (unlikely(IS_ERR(ret) && inode)) {
-+ ii_write_unlock(inode);
-+ iput(inode);
-+ inode = NULL;
++ if (inode) {
++ if (!IS_ERR(ret))
++ iput(inode);
++ else {
++ ii_write_unlock(inode);
++ iput(inode);
++ inode = NULL;
++ }
+ }
+
+out_unlock:
@@ -18191,7 +18437,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ au_hn_imtx_unlock(p->hdir);
+}
+
-+static int au_pin_hdir_lock(struct au_pin *p)
++int au_pin_hdir_lock(struct au_pin *p)
+{
+ int err;
+
@@ -18405,7 +18651,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
+ */
+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
-+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
++int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
+{
+ int err;
+ struct inode *inode;
@@ -18425,25 +18671,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ return err;
+}
+
-+#define AuIcpup_DID_CPUP 1
-+#define au_ftest_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;
-+ unsigned char pin_flags;
-+ aufs_bindex_t btgt;
-+ unsigned int udba;
-+ struct au_pin pin;
-+ struct path h_path;
-+ struct inode *h_inode;
-+};
-+
-+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
-+ struct au_icpup_args *a)
++int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
++ struct au_icpup_args *a)
+{
+ int err;
+ loff_t sz;
@@ -18485,11 +18714,13 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+
+ a->h_path.dentry = au_h_dptr(dentry, bstart);
+ a->h_inode = a->h_path.dentry->d_inode;
-+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
+ sz = -1;
-+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
-+ sz = ia->ia_size;
-+ mutex_unlock(&a->h_inode->i_mutex);
++ if (ia && (ia->ia_valid & ATTR_SIZE)) {
++ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++ if (ia->ia_size < i_size_read(a->h_inode))
++ sz = ia->ia_size;
++ mutex_unlock(&a->h_inode->i_mutex);
++ }
+
+ hi_wh = NULL;
+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
@@ -18671,6 +18902,99 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ return err;
+}
+
++#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
++static int au_h_path_to_set_attr(struct dentry *dentry,
++ struct au_icpup_args *a, struct path *h_path)
++{
++ int err;
++ struct super_block *sb;
++
++ sb = dentry->d_sb;
++ a->udba = au_opt_udba(sb);
++ /* no d_unlinked(), to set UDBA_NONE for root */
++ if (d_unhashed(dentry))
++ a->udba = AuOpt_UDBA_NONE;
++ if (a->udba != AuOpt_UDBA_NONE) {
++ AuDebugOn(IS_ROOT(dentry));
++ err = au_reval_for_attr(dentry, au_sigen(sb));
++ if (unlikely(err))
++ goto out;
++ }
++ err = au_pin_and_icpup(dentry, /*ia*/NULL, a);
++ if (unlikely(err < 0))
++ goto out;
++
++ h_path->dentry = a->h_path.dentry;
++ h_path->mnt = au_sbr_mnt(sb, a->btgt);
++
++out:
++ return err;
++}
++
++ssize_t au_srxattr(struct dentry *dentry, struct au_srxattr *arg)
++{
++ int err;
++ struct path h_path;
++ struct super_block *sb;
++ struct au_icpup_args *a;
++ struct inode *inode, *h_inode;
++
++ inode = dentry->d_inode;
++ IMustLock(inode);
++
++ err = -ENOMEM;
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++
++ sb = dentry->d_sb;
++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++ if (unlikely(err))
++ goto out_kfree;
++
++ h_path.dentry = NULL; /* silence gcc */
++ di_write_lock_child(dentry);
++ err = au_h_path_to_set_attr(dentry, a, &h_path);
++ if (unlikely(err))
++ goto out_di;
++
++ mutex_unlock(&a->h_inode->i_mutex);
++ switch (arg->type) {
++ case AU_XATTR_SET:
++ err = vfsub_setxattr(h_path.dentry,
++ arg->u.set.name, arg->u.set.value,
++ arg->u.set.size, arg->u.set.flags);
++ break;
++ case AU_XATTR_REMOVE:
++ err = vfsub_removexattr(h_path.dentry, arg->u.remove.name);
++ break;
++ case AU_ACL_SET:
++ err = -EOPNOTSUPP;
++ h_inode = h_path.dentry->d_inode;
++ if (h_inode->i_op->set_acl)
++ err = h_inode->i_op->set_acl(h_inode,
++ arg->u.acl_set.acl,
++ arg->u.acl_set.type);
++ break;
++ }
++ if (!err)
++ au_cpup_attr_timesizes(inode);
++
++ au_unpin(&a->pin);
++ if (unlikely(err))
++ au_update_dbstart(dentry);
++
++out_di:
++ di_write_unlock(dentry);
++ si_read_unlock(sb);
++out_kfree:
++ kfree(a);
++out:
++ AuTraceErr(err);
++ return err;
++}
++#endif
++
+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
+ unsigned int nlink)
+{
@@ -18700,22 +19024,25 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ spin_unlock(&inode->i_lock);
+}
+
-+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
-+ struct dentry *dentry, struct kstat *st)
++/*
++ * common routine for aufs_getattr() and aufs_getxattr().
++ * returns zero or negative (an error).
++ * @dentry will be read-locked in success.
++ */
++int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path)
+{
+ int err;
+ unsigned int mnt_flags, sigen;
++ unsigned char udba_none;
+ aufs_bindex_t bindex;
-+ unsigned char udba_none, positive;
+ struct super_block *sb, *h_sb;
+ struct inode *inode;
-+ struct path h_path;
+
++ h_path->mnt = NULL;
++ h_path->dentry = NULL;
++
++ err = 0;
+ sb = dentry->d_sb;
-+ inode = dentry->d_inode;
-+ 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);
+
@@ -18726,43 +19053,74 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ if (!err) {
+ di_read_lock_child(dentry, AuLock_IR);
+ err = au_dbrange_test(dentry);
-+ if (unlikely(err))
-+ goto out_unlock;
++ if (unlikely(err)) {
++ di_read_unlock(dentry, AuLock_IR);
++ goto out;
++ }
+ } else {
+ AuDebugOn(IS_ROOT(dentry));
+ di_write_lock_child(dentry);
+ err = au_dbrange_test(dentry);
+ if (!err)
+ err = au_reval_for_attr(dentry, sigen);
-+ di_downgrade_lock(dentry, AuLock_IR);
-+ if (unlikely(err))
-+ goto out_unlock;
++ if (!err)
++ di_downgrade_lock(dentry, AuLock_IR);
++ else {
++ di_write_unlock(dentry);
++ goto out;
++ }
+ }
+ } else
+ di_read_lock_child(dentry, AuLock_IR);
+
++ inode = dentry->d_inode;
+ bindex = au_ibstart(inode);
-+ h_path.mnt = au_sbr_mnt(sb, bindex);
-+ h_sb = h_path.mnt->mnt_sb;
-+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
-+ goto out_fill; /* success */
++ h_path->mnt = au_sbr_mnt(sb, bindex);
++ h_sb = h_path->mnt->mnt_sb;
++ if (!force
++ && !au_test_fs_bad_iattr(h_sb)
++ && udba_none)
++ goto out; /* success */
+
-+ h_path.dentry = NULL;
+ if (au_dbstart(dentry) == bindex)
-+ h_path.dentry = dget(au_h_dptr(dentry, bindex));
++ h_path->dentry = au_h_dptr(dentry, bindex);
+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
-+ h_path.dentry = au_plink_lkup(inode, bindex);
-+ if (IS_ERR(h_path.dentry))
-+ goto out_fill; /* pretending success */
++ h_path->dentry = au_plink_lkup(inode, bindex);
++ if (IS_ERR(h_path->dentry))
++ /* pretending success */
++ h_path->dentry = NULL;
++ else
++ dput(h_path->dentry);
+ }
-+ /* illegally overlapped or something */
++
++out:
++ return err;
++}
++
++static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
++ struct dentry *dentry, struct kstat *st)
++{
++ int err;
++ unsigned char positive;
++ struct path h_path;
++ struct inode *inode;
++ struct super_block *sb;
++
++ inode = dentry->d_inode;
++ sb = dentry->d_sb;
++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++ if (unlikely(err))
++ goto out;
++ err = au_h_path_getattr(dentry, /*force*/0, &h_path);
++ if (unlikely(err))
++ goto out_si;
+ if (unlikely(!h_path.dentry))
++ /* illegally overlapped or something */
+ goto out_fill; /* pretending success */
+
+ positive = !!h_path.dentry->d_inode;
+ if (positive)
+ err = vfs_getattr(&h_path, st);
-+ dput(h_path.dentry);
+ if (!err) {
+ if (positive)
+ au_refresh_iattr(inode, st,
@@ -18770,12 +19128,13 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ goto out_fill; /* success */
+ }
+ AuTraceErr(err);
-+ goto out_unlock;
++ goto out_di;
+
+out_fill:
+ generic_fillattr(inode, st);
-+out_unlock:
++out_di:
+ di_read_unlock(dentry, AuLock_IR);
++out_si:
+ si_read_unlock(sb);
+out:
+ AuTraceErr(err);
@@ -18911,9 +19270,21 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+
+struct inode_operations aufs_symlink_iop = {
+ .permission = aufs_permission,
++#ifdef CONFIG_FS_POSIX_ACL
++ .get_acl = aufs_get_acl,
++ .set_acl = aufs_set_acl, /* unsupport for symlink? */
++#endif
++
+ .setattr = aufs_setattr,
+ .getattr = aufs_getattr,
+
++#ifdef CONFIG_AUFS_XATTR
++ .setxattr = aufs_setxattr,
++ .getxattr = aufs_getxattr,
++ .listxattr = aufs_listxattr,
++ .removexattr = aufs_removexattr,
++#endif
++
+ .readlink = aufs_readlink,
+ .follow_link = aufs_follow_link,
+ .put_link = aufs_put_link,
@@ -18933,9 +19304,21 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+ .rename = aufs_rename,
+
+ .permission = aufs_permission,
++#ifdef CONFIG_FS_POSIX_ACL
++ .get_acl = aufs_get_acl,
++ .set_acl = aufs_set_acl,
++#endif
++
+ .setattr = aufs_setattr,
+ .getattr = aufs_getattr,
+
++#ifdef CONFIG_AUFS_XATTR
++ .setxattr = aufs_setxattr,
++ .getxattr = aufs_getxattr,
++ .listxattr = aufs_listxattr,
++ .removexattr = aufs_removexattr,
++#endif
++
+ .update_time = aufs_update_time,
+ /* no support for atomic_open() */
+
@@ -18944,14 +19327,26 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
+
+struct inode_operations aufs_iop = {
+ .permission = aufs_permission,
++#ifdef CONFIG_FS_POSIX_ACL
++ .get_acl = aufs_get_acl,
++ .set_acl = aufs_set_acl,
++#endif
++
+ .setattr = aufs_setattr,
+ .getattr = aufs_getattr,
+
++#ifdef CONFIG_AUFS_XATTR
++ .setxattr = aufs_setxattr,
++ .getxattr = aufs_getxattr,
++ .listxattr = aufs_listxattr,
++ .removexattr = aufs_removexattr,
++#endif
++
+ .update_time = aufs_update_time
+};
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 2014-08-14 10:15:45.121942630 +0200
++++ linux/fs/aufs/i_op_del.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,507 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -19462,7 +19857,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
+}
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 2014-08-14 10:15:45.128609525 +0200
++++ linux/fs/aufs/i_op_ren.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -20500,8 +20895,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
+}
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 2014-08-14 10:15:45.118609182 +0200
-@@ -0,0 +1,177 @@
++++ linux/fs/aufs/Kconfig 2015-01-25 13:00:38.627713742 +0100
+@@ -0,0 +1,185 @@
+config AUFS_FS
+ tristate "Aufs (Advanced multi layered unification filesystem) support"
+ help
@@ -20591,6 +20986,14 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
+ /* typedef unsigned long/int __kernel_ino_t */
+ /* alpha and s390x are int */
+
++config AUFS_XATTR
++ bool "support for XATTR/EA (including Security Labels)"
++ help
++ If your branch fs supports XATTR/EA and you want to make them
++ available in aufs too, then enable this opsion and specify the
++ branch attributes for EA.
++ See detail in aufs.5.
++
+config AUFS_FHSM
+ bool "File-based Hierarchical Storage Management"
+ help
@@ -20681,7 +21084,7 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
+endif
diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/loop.c 2014-01-30 21:10:02.850815069 +0100
++++ linux/fs/aufs/loop.c 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -20830,7 +21233,7 @@ diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
+}
diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/loop.h 2014-01-30 21:10:02.850815069 +0100
++++ linux/fs/aufs/loop.h 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -20886,7 +21289,7 @@ diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
+#endif /* __AUFS_LOOP_H__ */
diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/magic.mk 2014-01-30 21:10:02.850815069 +0100
++++ linux/fs/aufs/magic.mk 2015-01-25 13:00:38.631047076 +0100
@@ -0,0 +1,54 @@
+
+# defined in ${srctree}/fs/fuse/inode.c
@@ -20944,8 +21347,8 @@ diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
+endif
diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/Makefile 2014-08-14 10:15:45.118609182 +0200
-@@ -0,0 +1,42 @@
++++ linux/fs/aufs/Makefile 2015-01-25 13:00:38.627713742 +0100
+@@ -0,0 +1,44 @@
+
+include ${src}/magic.mk
+ifeq (${CONFIG_AUFS_FS},m)
@@ -20982,6 +21385,8 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
+aufs-$(CONFIG_AUFS_EXPORT) += export.o
++aufs-$(CONFIG_AUFS_XATTR) += xattr.o
++aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
+aufs-$(CONFIG_AUFS_POLL) += poll.o
+aufs-$(CONFIG_AUFS_RDU) += rdu.o
@@ -20990,7 +21395,7 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/module.c 2014-08-14 10:15:45.128609525 +0200
++++ linux/fs/aufs/module.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -21204,7 +21609,7 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
+module_exit(aufs_exit);
diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/module.h 2014-01-30 21:10:02.850815069 +0100
++++ linux/fs/aufs/module.h 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -21312,8 +21717,8 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
+#endif /* __AUFS_MODULE_H__ */
diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
--- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/mvdown.c 2014-08-14 10:15:45.128609525 +0200
-@@ -0,0 +1,657 @@
++++ linux/fs/aufs/mvdown.c 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2011-2014 Junjiro R. Okajima
+ *
@@ -21343,6 +21748,7 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+ struct dentry *h_parent;
+ struct au_hinode *hdir;
+ struct inode *h_dir, *h_inode;
++ struct au_pin pin;
+ } info[AUFS_MVDOWN_NARRAY];
+
+ struct aufs_mvdown mvdown;
@@ -21351,7 +21757,6 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+ struct super_block *sb;
+ aufs_bindex_t bopq, bwh, bfound;
+ unsigned char rename_lock;
-+ struct au_pin pin;
+};
+
+#define mvd_errno mvdown.au_errno
@@ -21365,12 +21770,14 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
++#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
+
+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
++#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
+
+#define AU_MVD_PR(flag, ...) do { \
+ if (flag) \
@@ -21447,22 +21854,44 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+
+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
++ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
++ au_opt_udba(a->sb),
++ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
++ AuTraceErr(err);
++ if (unlikely(err)) {
++ AU_MVD_PR(dmsg, "pin_dst failed\n");
++ goto out;
++ }
++
+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
+ a->rename_lock = 0;
-+ err = au_pin(&a->pin, a->dentry, a->mvd_bdst,
-+ au_opt_udba(a->sb),
-+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
-+ if (!err) {
-+ a->mvd_h_src_dir = a->mvd_h_src_parent->d_inode;
-+ mutex_lock_nested(&a->mvd_h_src_dir->i_mutex,
-+ AuLsc_I_PARENT3);
-+ } else
-+ AU_MVD_PR(dmsg, "pin failed\n");
-+ goto out;
++ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
++ AuLsc_DI_PARENT, AuLsc_I_PARENT3,
++ au_opt_udba(a->sb),
++ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
++ err = au_do_pin(&a->mvd_pin_src);
++ AuTraceErr(err);
++ a->mvd_h_src_dir = a->mvd_h_src_parent->d_inode;
++ if (unlikely(err)) {
++ AU_MVD_PR(dmsg, "pin_src failed\n");
++ goto out_dst;
++ }
++ goto out; /* success */
+ }
+
-+ err = 0;
+ a->rename_lock = 1;
++ au_pin_hdir_unlock(&a->mvd_pin_dst);
++ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
++ au_opt_udba(a->sb),
++ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
++ AuTraceErr(err);
++ a->mvd_h_src_dir = a->mvd_h_src_parent->d_inode;
++ if (unlikely(err)) {
++ AU_MVD_PR(dmsg, "pin_src failed\n");
++ au_pin_hdir_lock(&a->mvd_pin_dst);
++ goto out_dst;
++ }
++ au_pin_hdir_unlock(&a->mvd_pin_src);
+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
+ if (h_trap) {
@@ -21471,7 +21900,20 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+ err = (h_trap != a->mvd_h_dst_parent);
+ }
+ BUG_ON(err); /* it should never happen */
++ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
++ err = -EBUSY;
++ AuTraceErr(err);
++ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
++ a->mvd_h_dst_parent, a->mvd_hdir_dst);
++ au_pin_hdir_lock(&a->mvd_pin_src);
++ au_unpin(&a->mvd_pin_src);
++ au_pin_hdir_lock(&a->mvd_pin_dst);
++ goto out_dst;
++ }
++ goto out; /* success */
+
++out_dst:
++ au_unpin(&a->mvd_pin_dst);
+out:
+ AuTraceErr(err);
+ return err;
@@ -21479,12 +21921,16 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+
+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
+{
-+ if (!a->rename_lock) {
-+ mutex_unlock(&a->mvd_h_src_dir->i_mutex);
-+ au_unpin(&a->pin);
-+ } else
++ if (!a->rename_lock)
++ au_unpin(&a->mvd_pin_src);
++ else {
+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
++ au_pin_hdir_lock(&a->mvd_pin_src);
++ au_unpin(&a->mvd_pin_src);
++ au_pin_hdir_lock(&a->mvd_pin_dst);
++ }
++ au_unpin(&a->mvd_pin_dst);
+}
+
+/* copy-down the file */
@@ -21496,7 +21942,7 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+ .bdst = a->mvd_bdst,
+ .bsrc = a->mvd_bsrc,
+ .len = -1,
-+ .pin = &a->pin,
++ .pin = &a->mvd_pin_dst,
+ .flags = AuCpup_DTIME | AuCpup_HOPEN
+ };
+
@@ -21555,8 +22001,6 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+
+/*
+ * unlink the topmost h_dentry
-+ * Note: the target file MAY be modified by UDBA between this mutex_unlock() and
-+ * mutex_lock() in vfs_unlink(). in this case, such changes may be lost.
+ */
+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
+{
@@ -21629,6 +22073,8 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+ if (unlikely(err))
+ goto out_unlock;
+
++ AuDbg("%pd2, 0x%x, %d --> %d\n",
++ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
+ if (find_lower_writable(a) < 0)
+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
+
@@ -21664,7 +22110,7 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+ err = 0;
+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
+ if (au_dbstart(a->dentry) == a->mvd_bsrc
-+ && d_count(a->dentry) == 1
++ && au_dcount(a->dentry) == 1
+ && atomic_read(&a->inode->i_count) == 1
+ /* && a->mvd_h_src_inode->i_nlink == 1 */
+ && (!plinked || !au_plink_test(a->inode))
@@ -21673,8 +22119,8 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+
+ err = -EBUSY;
+ AU_MVD_PR(dmsg,
-+ "b%d, d{b%d, c%u?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
-+ a->mvd_bsrc, au_dbstart(a->dentry), d_count(a->dentry),
++ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
++ a->mvd_bsrc, au_dbstart(a->dentry), au_dcount(a->dentry),
+ atomic_read(&a->inode->i_count), a->inode->i_nlink,
+ a->mvd_h_src_inode->i_nlink,
+ plinked, plinked ? au_plink_test(a->inode) : 0);
@@ -21942,13 +22388,9 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+ if (unlikely(err))
+ goto out_parent;
+
-+ AuDbgDentry(dentry);
-+ AuDbgInode(args->inode);
+ err = au_do_mvdown(dmsg, args);
+ if (unlikely(err))
+ goto out_parent;
-+ AuDbgDentry(dentry);
-+ AuDbgInode(args->inode);
+
+ au_cpup_attr_timesizes(args->dir);
+ au_cpup_attr_timesizes(args->inode);
@@ -21973,8 +22415,8 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
+}
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 2014-08-14 10:15:45.128609525 +0200
-@@ -0,0 +1,1790 @@
++++ linux/fs/aufs/opts.c 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,1850 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -22027,6 +22469,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ Opt_verbose, Opt_noverbose,
+ Opt_sum, Opt_nosum, Opt_wsum,
+ Opt_dirperm1, Opt_nodirperm1,
++ Opt_acl, Opt_noacl,
+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
+};
+
@@ -22134,6 +22577,15 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ {Opt_wbr_copyup, "copyup=%s"},
+ {Opt_wbr_copyup, "copyup_policy=%s"},
+
++ /* generic VFS flag */
++#ifdef CONFIG_FS_POSIX_ACL
++ {Opt_acl, "acl"},
++ {Opt_noacl, "noacl"},
++#else
++ {Opt_ignore_silent, "acl"},
++ {Opt_ignore_silent, "noacl"},
++#endif
++
+ /* internal use for the scripts */
+ {Opt_ignore_silent, "si=%s"},
+
@@ -22195,8 +22647,15 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ /* general */
+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
++ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
++ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
++ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
++ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
++ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
++ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
++ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
+
+ /* ro/rr branch */
+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
@@ -22242,7 +22701,6 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ const char *p;
+ char *q;
+
-+ sz = 0;
+ q = str->a;
+ *q = 0;
+ p = au_optstr(&perm, brattr);
@@ -22264,7 +22722,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ } while (p);
+
+out:
-+ return sz;
++ return q - str->a;
+}
+
+static int noinline_for_stack br_perm_val(char *perm)
@@ -22302,6 +22760,17 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ val &= ~AuBrRAttr_Mask;
+ break;
+ }
++
++ /*
++ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
++ * does not treat it as an error, just warning.
++ * this is a tiny guard for the user operation.
++ */
++ if (val & AuBrAttr_UNPIN) {
++ bad |= AuBrAttr_UNPIN;
++ val &= ~AuBrAttr_UNPIN;
++ }
++
+ if (unlikely(bad)) {
+ sz = au_do_optstr_br_attr(&attr, bad);
+ AuDebugOn(!sz);
@@ -22691,6 +23160,12 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ case Opt_fhsm_sec:
+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
+ break;
++ case Opt_acl:
++ AuLabel(acl);
++ break;
++ case Opt_noacl:
++ AuLabel(noacl);
++ break;
+ default:
+ BUG();
+ }
@@ -23137,6 +23612,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ case Opt_wsum:
+ case Opt_rdblk_def:
+ case Opt_rdhash_def:
++ case Opt_acl:
++ case Opt_noacl:
+ err = 0;
+ opt->type = token;
+ break;
@@ -23406,6 +23883,13 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ au_fclr_opts(opts->flags, TRUNC_XIB);
+ break;
+
++ case Opt_acl:
++ sb->s_flags |= MS_POSIXACL;
++ break;
++ case Opt_noacl:
++ sb->s_flags &= ~MS_POSIXACL;
++ break;
++
+ default:
+ err = 0;
+ break;
@@ -23556,8 +24040,17 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ skip = 0;
+ h_dir = au_h_iptr(dir, bindex);
+ br = au_sbr(sb, bindex);
-+ do_free = 0;
+
++ if ((br->br_perm & AuBrAttr_ICEX)
++ && !h_dir->i_op->listxattr)
++ br->br_perm &= ~AuBrAttr_ICEX;
++#if 0
++ if ((br->br_perm & AuBrAttr_ICEX_SEC)
++ && (au_br_sb(br)->s_flags & MS_NOSEC))
++ br->br_perm &= ~AuBrAttr_ICEX_SEC;
++#endif
++
++ do_free = 0;
+ wbr = br->br_wbr;
+ if (wbr)
+ wbr_wh_read_lock(wbr);
@@ -23613,10 +24106,19 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+ }
+ }
+
-+ if (fhsm >= 2)
++ if (fhsm >= 2) {
+ au_fset_si(sbinfo, FHSM);
-+ else
++ for (bindex = bend; bindex >= 0; bindex--) {
++ br = au_sbr(sb, bindex);
++ if (au_br_fhsm(br->br_perm)) {
++ au_fhsm_set_bottom(sb, bindex);
++ break;
++ }
++ }
++ } else {
+ au_fclr_si(sbinfo, FHSM);
++ au_fhsm_set_bottom(sb, -1);
++ }
+
+ return err;
+}
@@ -23767,7 +24269,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
+}
diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/opts.h 2014-08-14 10:15:45.128609525 +0200
++++ linux/fs/aufs/opts.h 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -23984,7 +24486,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
+#endif /* __AUFS_OPTS_H__ */
diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/plink.c 2014-01-30 21:10:02.857481956 +0100
++++ linux/fs/aufs/plink.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -24520,7 +25022,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
+}
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 2014-01-30 21:10:02.857481956 +0100
++++ linux/fs/aufs/poll.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -24577,9 +25079,112 @@ diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
+ AuTraceErr((int)mask);
+ return mask;
+}
+diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c
+--- /usr/share/empty/fs/aufs/posix_acl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/posix_acl.c 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,99 @@
++/*
++ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
++ */
++
++/*
++ * posix acl operations
++ */
++
++#include <linux/fs.h>
++#include <linux/posix_acl.h>
++#include "aufs.h"
++
++struct posix_acl *aufs_get_acl(struct inode *inode, int type)
++{
++ struct posix_acl *acl;
++ int err;
++ aufs_bindex_t bindex;
++ struct inode *h_inode;
++ struct super_block *sb;
++
++ acl = NULL;
++ sb = inode->i_sb;
++ si_read_lock(sb, AuLock_FLUSH);
++ ii_read_lock_child(inode);
++ if (!(sb->s_flags & MS_POSIXACL))
++ goto out;
++
++ bindex = au_ibstart(inode);
++ h_inode = au_h_iptr(inode, bindex);
++ if (unlikely(!h_inode
++ || ((h_inode->i_mode & S_IFMT)
++ != (inode->i_mode & S_IFMT)))) {
++ err = au_busy_or_stale();
++ acl = ERR_PTR(err);
++ goto out;
++ }
++
++ /* always topmost only */
++ acl = get_acl(h_inode, type);
++
++out:
++ ii_read_unlock(inode);
++ si_read_unlock(sb);
++
++ AuTraceErrPtr(acl);
++ return acl;
++}
++
++int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
++{
++ int err;
++ ssize_t ssz;
++ struct dentry *dentry;
++ struct au_srxattr arg = {
++ .type = AU_ACL_SET,
++ .u.acl_set = {
++ .acl = acl,
++ .type = type
++ },
++ };
++
++ mutex_lock(&inode->i_mutex);
++ if (inode->i_ino == AUFS_ROOT_INO)
++ dentry = dget(inode->i_sb->s_root);
++ else {
++ dentry = d_find_alias(inode);
++ if (!dentry)
++ dentry = d_find_any_alias(inode);
++ if (!dentry) {
++ pr_warn("cannot handle this inode, "
++ "please report to aufs-users ML\n");
++ err = -ENOENT;
++ goto out;
++ }
++ }
++
++ ssz = au_srxattr(dentry, &arg);
++ dput(dentry);
++ err = ssz;
++ if (ssz >= 0)
++ err = 0;
++
++out:
++ mutex_unlock(&inode->i_mutex);
++ return err;
++}
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 2014-01-30 21:10:02.857481956 +0100
++++ linux/fs/aufs/procfs.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2010-2014 Junjiro R. Okajima
@@ -24752,7 +25357,7 @@ diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
+}
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 2014-01-30 21:10:02.857481956 +0100
++++ linux/fs/aufs/rdu.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -25144,7 +25749,7 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
+#endif
diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/rwsem.h 2014-08-14 10:15:45.128609525 +0200
++++ linux/fs/aufs/rwsem.h 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -25339,7 +25944,7 @@ diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
+#endif /* __AUFS_RWSEM_H__ */
diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sbinfo.c 2014-08-14 10:15:45.128609525 +0200
++++ linux/fs/aufs/sbinfo.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -25696,7 +26301,7 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
+}
diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/spl.h 2014-01-30 21:10:02.857481956 +0100
++++ linux/fs/aufs/spl.h 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -25811,8 +26416,8 @@ diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
+#endif /* __AUFS_SPL_H__ */
diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/super.c 2014-08-14 10:15:45.131942973 +0200
-@@ -0,0 +1,1004 @@
++++ linux/fs/aufs/super.c 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,1009 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -26052,8 +26657,11 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
+ seq_printf(m, "," #str "=%u", val); \
+} while (0)
+
-+ /* lock free root dinfo */
+ sb = dentry->d_sb;
++ if (sb->s_flags & MS_POSIXACL)
++ seq_puts(m, ",acl");
++
++ /* lock free root dinfo */
+ si_noflush_read_lock(sb);
+ sbinfo = au_sbi(sb);
+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
@@ -26711,7 +27319,9 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
+ sb->s_d_op = &aufs_dop;
+ sb->s_magic = AUFS_SUPER_MAGIC;
+ sb->s_maxbytes = 0;
++ sb->s_stack_depth = 1;
+ au_export_init(sb);
++ /* au_xattr_init(sb); */
+
+ err = alloc_root(sb);
+ if (unlikely(err)) {
@@ -26819,8 +27429,8 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
+};
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 2014-08-14 10:15:45.131942973 +0200
-@@ -0,0 +1,642 @@
++++ linux/fs/aufs/super.h 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -26907,8 +27517,9 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+ wait_queue_head_t fhsm_wqh;
+ atomic_t fhsm_readable;
+
-+ /* only this is protected by si_rwsem */
++ /* these are protected by si_rwsem */
+ unsigned long fhsm_expire;
++ aufs_bindex_t fhsm_bottom;
+#endif
+};
+
@@ -27155,6 +27766,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+void au_fhsm_wrote_all(struct super_block *sb, int force);
+int au_fhsm_fd(struct super_block *sb, int oflags);
+int au_fhsm_br_alloc(struct au_branch *br);
++void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex);
+void au_fhsm_fin(struct super_block *sb);
+void au_fhsm_init(struct au_sbinfo *sbinfo);
+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec);
@@ -27164,8 +27776,9 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+ int force)
+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force)
+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags)
-+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm);
-+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br);
++AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm)
++AuStubInt0(au_fhsm_br_alloc, struct au_branch *br)
++AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex)
+AuStubVoid(au_fhsm_fin, struct super_block *sb)
+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo)
+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec)
@@ -27202,10 +27815,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+AuStubInt0(au_xigen_new, struct inode *inode)
+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
+AuStubVoid(au_xigen_clr, struct super_block *sb)
-+static inline int au_busy_or_stale(void)
-+{
-+ return -EBUSY;
-+}
++AuStub(int, au_busy_or_stale, return -EBUSY, void)
+#endif /* CONFIG_AUFS_EXPORT */
+
+/* ---------------------------------------------------------------------- */
@@ -27247,8 +27857,8 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
+#else
+AuStubVoid(au_sbilist_init, void)
-+AuStubVoid(au_sbilist_add, struct super_block*)
-+AuStubVoid(au_sbilist_del, struct super_block*)
++AuStubVoid(au_sbilist_add, struct super_block *sb)
++AuStubVoid(au_sbilist_del, struct super_block *sb)
+AuStubVoid(au_sbilist_lock, void)
+AuStubVoid(au_sbilist_unlock, void)
+#define AuGFP_SBILIST GFP_NOFS
@@ -27259,7 +27869,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
+{
+ /*
-+ * This function is a dynamic '__init' fucntion actually,
++ * This function is a dynamic '__init' function actually,
+ * so the tiny check for si_rwsem is unnecessary.
+ */
+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
@@ -27288,8 +27898,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+ bit = si_pid_bit();
+ if (bit < PID_MAX_DEFAULT)
+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
-+ else
-+ return si_pid_test_slow(sb);
++ return si_pid_test_slow(sb);
+}
+
+static inline void si_pid_set(struct super_block *sb)
@@ -27465,7 +28074,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
+#endif /* __AUFS_SUPER_H__ */
diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sysaufs.c 2014-01-30 21:10:02.857481956 +0100
++++ linux/fs/aufs/sysaufs.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -27573,8 +28182,8 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
+}
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 2014-08-14 10:15:45.131942973 +0200
-@@ -0,0 +1,107 @@
++++ linux/fs/aufs/sysaufs.h 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -27661,14 +28270,8 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
+#define sysaufs_attr_group NULL
+
+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
-+
-+static inline
-+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
-+ char *buf)
-+{
-+ return 0;
-+}
-+
++AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj,
++ struct attribute *attr, char *buf)
+AuStubVoid(sysaufs_br_init, struct au_branch *br)
+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
@@ -27684,7 +28287,7 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
+#endif /* __SYSAUFS_H__ */
diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sysfs.c 2014-08-14 10:15:45.131942973 +0200
++++ linux/fs/aufs/sysfs.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -28060,7 +28663,7 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
+}
diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/sysrq.c 2014-08-14 10:15:45.131942973 +0200
++++ linux/fs/aufs/sysrq.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -28221,7 +28824,7 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
+}
diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/vdir.c 2014-08-14 10:15:45.131942973 +0200
++++ linux/fs/aufs/vdir.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -29114,8 +29717,8 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
+}
diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/vfsub.c 2014-08-14 10:16:04.515942371 +0200
-@@ -0,0 +1,782 @@
++++ linux/fs/aufs/vfsub.c 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,796 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -29276,7 +29879,9 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+ if (unlikely(err))
+ goto out;
+
++ lockdep_off();
+ err = vfs_create(dir, path->dentry, mode, want_excl);
++ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
+ int did;
@@ -29307,7 +29912,9 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+ if (unlikely(err))
+ goto out;
+
++ lockdep_off();
+ err = vfs_symlink(dir, path->dentry, symname);
++ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
+ int did;
@@ -29338,7 +29945,9 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+ if (unlikely(err))
+ goto out;
+
++ lockdep_off();
+ err = vfs_mknod(dir, path->dentry, mode, dev);
++ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
+ int did;
@@ -29464,7 +30073,9 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+ if (unlikely(err))
+ goto out;
+
++ lockdep_off();
+ err = vfs_mkdir(dir, path->dentry, mode);
++ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
+ int did;
@@ -29710,9 +30321,11 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+ int err, do_sio, wkq_err;
+
+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
-+ if (!do_sio)
++ if (!do_sio) {
++ lockdep_off();
+ err = vfsub_mkdir(dir, path, mode);
-+ else {
++ lockdep_on();
++ } else {
+ struct au_vfsub_mkdir_args args = {
+ .errp = &err,
+ .dir = dir,
@@ -29744,9 +30357,11 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+ int err, do_sio, wkq_err;
+
+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
-+ if (!do_sio)
++ if (!do_sio) {
++ lockdep_off();
+ err = vfsub_rmdir(dir, path);
-+ else {
++ lockdep_on();
++ } else {
+ struct au_vfsub_rmdir_args args = {
+ .errp = &err,
+ .dir = dir,
@@ -29779,8 +30394,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+
+ *a->errp = -EPERM;
+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
++ lockdep_off();
+ *a->errp = notify_change(a->path->dentry, a->ia,
+ a->delegated_inode);
++ lockdep_on();
+ if (!*a->errp)
+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
+ }
@@ -29836,7 +30453,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+ struct dentry *d = a->path->dentry;
+ struct inode *h_inode;
+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
-+ && d_count(d) == 1);
++ && au_dcount(d) == 1);
+
+ IMustLock(a->dir);
+
@@ -29900,8 +30517,8 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
+}
diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/vfsub.h 2014-08-14 10:15:45.131942973 +0200
-@@ -0,0 +1,284 @@
++++ linux/fs/aufs/vfsub.h 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -29931,6 +30548,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
+#include <linux/fs.h>
+#include <linux/lglock.h>
+#include <linux/mount.h>
++#include <linux/xattr.h>
+#include "debug.h"
+
+/* copied from linux/fs/internal.h */
@@ -29944,7 +30562,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
+/* reduce? gave up. */
+enum {
-+ AuLsc_I_Begin = I_MUTEX_NONDIR2, /* 4 */
++ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */
+ AuLsc_I_PARENT, /* lower inode, parent first */
+ AuLsc_I_PARENT2, /* copyup dirs */
+ AuLsc_I_PARENT3, /* copyup wh */
@@ -30184,11 +30802,36 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
+int vfsub_unlink(struct inode *dir, struct path *path,
+ struct inode **delegated_inode, int force);
+
++/* ---------------------------------------------------------------------- */
++
++static inline int vfsub_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
++{
++ int err;
++
++ lockdep_off();
++ err = vfs_setxattr(dentry, name, value, size, flags);
++ lockdep_on();
++
++ return err;
++}
++
++static inline int vfsub_removexattr(struct dentry *dentry, const char *name)
++{
++ int err;
++
++ lockdep_off();
++ err = vfs_removexattr(dentry, name);
++ lockdep_on();
++
++ return err;
++}
++
+#endif /* __KERNEL__ */
+#endif /* __AUFS_VFSUB_H__ */
diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wbr_policy.c 2014-08-14 10:15:45.131942973 +0200
++++ linux/fs/aufs/wbr_policy.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -30957,7 +31600,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
+};
diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/whout.c 2014-08-14 10:15:45.131942973 +0200
++++ linux/fs/aufs/whout.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,1056 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -31303,9 +31946,9 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
+
+/*
+ * returns tri-state,
-+ * minus: error, caller should print the mesage
++ * minus: error, caller should print the message
+ * zero: succuess
-+ * plus: error, caller should NOT print the mesage
++ * plus: error, caller should NOT print the message
+ */
+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
+ int do_plink, struct au_wh_base base[],
@@ -32017,7 +32660,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
+}
diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/whout.h 2014-08-14 10:15:45.131942973 +0200
++++ linux/fs/aufs/whout.h 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -32106,7 +32749,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
+#endif /* __AUFS_WHOUT_H__ */
diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wkq.c 2014-08-14 10:16:04.515942371 +0200
++++ linux/fs/aufs/wkq.c 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -32323,7 +32966,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
+}
diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/wkq.h 2014-01-30 21:10:02.860815399 +0100
++++ linux/fs/aufs/wkq.h 2015-01-25 13:00:38.634380408 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
@@ -32416,10 +33059,348 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_WKQ_H__ */
+diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
+--- /usr/share/empty/fs/aufs/xattr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/fs/aufs/xattr.c 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,334 @@
++/*
++ * Copyright (C) 2014 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, see <http://www.gnu.org/licenses/>.
++ */
++
++/*
++ * handling xattr functions
++ */
++
++#include <linux/xattr.h>
++#include "aufs.h"
++
++static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
++{
++ if (!ignore_flags)
++ goto out;
++ switch (err) {
++ case -ENOMEM:
++ case -EDQUOT:
++ goto out;
++ }
++
++ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
++ err = 0;
++ goto out;
++ }
++
++#define cmp(brattr, prefix) do { \
++ if (!strncmp(name, XATTR_##prefix##_PREFIX, \
++ XATTR_##prefix##_PREFIX_LEN)) { \
++ if (ignore_flags & AuBrAttr_ICEX_##brattr) \
++ err = 0; \
++ goto out; \
++ } \
++ } while (0)
++
++ cmp(SEC, SECURITY);
++ cmp(SYS, SYSTEM);
++ cmp(TR, TRUSTED);
++ cmp(USR, USER);
++#undef cmp
++
++ if (ignore_flags & AuBrAttr_ICEX_OTH)
++ err = 0;
++
++out:
++ return err;
++}
++
++static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
++
++static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
++ char *name, char **buf, unsigned int ignore_flags)
++{
++ int err;
++ ssize_t ssz;
++ struct inode *h_idst;
++
++ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
++ err = ssz;
++ if (unlikely(err <= 0)) {
++ AuTraceErr(err);
++ if (err == -ENODATA
++ || (err == -EOPNOTSUPP
++ && (ignore_flags & au_xattr_out_of_list)))
++ err = 0;
++ goto out;
++ }
++
++ /* unlock it temporary */
++ h_idst = h_dst->d_inode;
++ mutex_unlock(&h_idst->i_mutex);
++ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
++ mutex_lock_nested(&h_idst->i_mutex, AuLsc_I_CHILD2);
++ if (unlikely(err)) {
++ AuDbg("%s, err %d\n", name, err);
++ err = au_xattr_ignore(err, name, ignore_flags);
++ }
++
++out:
++ return err;
++}
++
++int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags)
++{
++ int err, unlocked, acl_access, acl_default;
++ ssize_t ssz;
++ struct inode *h_isrc, *h_idst;
++ char *value, *p, *o, *e;
++
++ /* try stopping to update the source inode while we are referencing */
++ /* there should not be the parent-child relation ship between them */
++ h_isrc = h_src->d_inode;
++ h_idst = h_dst->d_inode;
++ mutex_unlock(&h_idst->i_mutex);
++ mutex_lock_nested(&h_isrc->i_mutex, AuLsc_I_CHILD);
++ mutex_lock_nested(&h_idst->i_mutex, AuLsc_I_CHILD2);
++ unlocked = 0;
++
++ /* some filesystems don't list POSIX ACL, for example tmpfs */
++ ssz = vfs_listxattr(h_src, NULL, 0);
++ err = ssz;
++ if (unlikely(err < 0)) {
++ AuTraceErr(err);
++ if (err == -ENODATA
++ || err == -EOPNOTSUPP)
++ err = 0; /* ignore */
++ goto out;
++ }
++
++ err = 0;
++ p = NULL;
++ o = NULL;
++ if (ssz) {
++ err = -ENOMEM;
++ p = kmalloc(ssz, GFP_NOFS);
++ o = p;
++ if (unlikely(!p))
++ goto out;
++ err = vfs_listxattr(h_src, p, ssz);
++ }
++ mutex_unlock(&h_isrc->i_mutex);
++ unlocked = 1;
++ AuDbg("err %d, ssz %zd\n", err, ssz);
++ if (unlikely(err < 0))
++ goto out_free;
++
++ err = 0;
++ e = p + ssz;
++ value = NULL;
++ acl_access = 0;
++ acl_default = 0;
++ while (!err && p < e) {
++ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
++ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
++ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
++ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
++ - 1);
++ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags);
++ p += strlen(p) + 1;
++ }
++ AuTraceErr(err);
++ ignore_flags |= au_xattr_out_of_list;
++ if (!err && !acl_access) {
++ err = au_do_cpup_xattr(h_dst, h_src,
++ XATTR_NAME_POSIX_ACL_ACCESS, &value,
++ ignore_flags);
++ AuTraceErr(err);
++ }
++ if (!err && !acl_default) {
++ err = au_do_cpup_xattr(h_dst, h_src,
++ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
++ ignore_flags);
++ AuTraceErr(err);
++ }
++
++ kfree(value);
++
++out_free:
++ kfree(o);
++out:
++ if (!unlocked)
++ mutex_unlock(&h_isrc->i_mutex);
++ AuTraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++enum {
++ AU_XATTR_LIST,
++ AU_XATTR_GET
++};
++
++struct au_lgxattr {
++ int type;
++ union {
++ struct {
++ char *list;
++ size_t size;
++ } list;
++ struct {
++ const char *name;
++ void *value;
++ size_t size;
++ } get;
++ } u;
++};
++
++static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
++{
++ ssize_t err;
++ struct path h_path;
++ struct super_block *sb;
++
++ sb = dentry->d_sb;
++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++ if (unlikely(err))
++ goto out;
++ err = au_h_path_getattr(dentry, /*force*/1, &h_path);
++ if (unlikely(err))
++ goto out_si;
++ if (unlikely(!h_path.dentry))
++ /* illegally overlapped or something */
++ goto out_di; /* pretending success */
++
++ /* always topmost entry only */
++ switch (arg->type) {
++ case AU_XATTR_LIST:
++ err = vfs_listxattr(h_path.dentry,
++ arg->u.list.list, arg->u.list.size);
++ break;
++ case AU_XATTR_GET:
++ err = vfs_getxattr(h_path.dentry,
++ arg->u.get.name, arg->u.get.value,
++ arg->u.get.size);
++ break;
++ }
++
++out_di:
++ di_read_unlock(dentry, AuLock_IR);
++out_si:
++ si_read_unlock(sb);
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
++{
++ struct au_lgxattr arg = {
++ .type = AU_XATTR_LIST,
++ .u.list = {
++ .list = list,
++ .size = size
++ },
++ };
++
++ return au_lgxattr(dentry, &arg);
++}
++
++ssize_t aufs_getxattr(struct dentry *dentry, const char *name, void *value,
++ size_t size)
++{
++ struct au_lgxattr arg = {
++ .type = AU_XATTR_GET,
++ .u.get = {
++ .name = name,
++ .value = value,
++ .size = size
++ },
++ };
++
++ return au_lgxattr(dentry, &arg);
++}
++
++int aufs_setxattr(struct dentry *dentry, const char *name, const void *value,
++ size_t size, int flags)
++{
++ struct au_srxattr arg = {
++ .type = AU_XATTR_SET,
++ .u.set = {
++ .name = name,
++ .value = value,
++ .size = size,
++ .flags = flags
++ },
++ };
++
++ return au_srxattr(dentry, &arg);
++}
++
++int aufs_removexattr(struct dentry *dentry, const char *name)
++{
++ struct au_srxattr arg = {
++ .type = AU_XATTR_REMOVE,
++ .u.remove = {
++ .name = name
++ },
++ };
++
++ return au_srxattr(dentry, &arg);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#if 0
++static size_t au_xattr_list(struct dentry *dentry, char *list, size_t list_size,
++ const char *name, size_t name_len, int type)
++{
++ return aufs_listxattr(dentry, list, list_size);
++}
++
++static int au_xattr_get(struct dentry *dentry, const char *name, void *buffer,
++ size_t size, int type)
++{
++ return aufs_getxattr(dentry, name, buffer, size);
++}
++
++static int au_xattr_set(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int type)
++{
++ return aufs_setxattr(dentry, name, value, size, flags);
++}
++
++static const struct xattr_handler au_xattr_handler = {
++ /* no prefix, no flags */
++ .list = au_xattr_list,
++ .get = au_xattr_get,
++ .set = au_xattr_set
++ /* why no remove? */
++};
++
++static const struct xattr_handler *au_xattr_handlers[] = {
++ &au_xattr_handler
++};
++
++void au_xattr_init(struct super_block *sb)
++{
++ /* sb->s_xattr = au_xattr_handlers; */
++}
++#endif
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 2014-08-14 10:16:04.515942371 +0200
-@@ -0,0 +1,1316 @@
++++ linux/fs/aufs/xino.c 2015-01-25 13:00:38.634380408 +0100
+@@ -0,0 +1,1318 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -33648,6 +34629,8 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
+
+ /* reset all */
+ AuIOErr("failed creating xino(%d).\n", err);
++ au_xigen_clr(sb);
++ xino_clear_xib(sb);
+
+out:
+ dput(parent);
@@ -33738,8 +34721,8 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
+}
diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/include/uapi/linux/aufs_type.h 2014-08-14 10:16:04.522609267 +0200
-@@ -0,0 +1,380 @@
++++ linux/include/uapi/linux/aufs_type.h 2015-01-25 13:00:38.637713742 +0100
+@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2005-2014 Junjiro R. Okajima
+ *
@@ -33781,7 +34764,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin
+
+#include <linux/limits.h>
+
-+#define AUFS_VERSION "3.16-20140811"
++#define AUFS_VERSION "3.18.1+-20150119"
+
+/* todo? move this to linux-2.6.19/include/magic.h */
+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -33863,6 +34846,12 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin
+#define AUFS_BRATTR_COO_ALL "coo_all"
+#define AUFS_BRATTR_FHSM "fhsm"
+#define AUFS_BRATTR_UNPIN "unpin"
++#define AUFS_BRATTR_ICEX "icex"
++#define AUFS_BRATTR_ICEX_SEC "icexsec"
<Skipped 382 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/kernel.git/commitdiff/c1595e4220910ac55995380e00392abc3a6e934e
More information about the pld-cvs-commit
mailing list