[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