[packages/kernel] - up to 4.7.1

arekm arekm at pld-linux.org
Wed Aug 17 18:37:51 CEST 2016


commit f0c0a0075ebbd8e5d2b07223d3e6a049d302da27
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Wed Aug 17 18:36:56 2016 +0200

    - up to 4.7.1

 kernel-apparmor.patch |  22 --
 kernel-aufs4.patch    | 817 +++++++++++++++++++++++++++++++-------------------
 kernel.spec           |   4 +-
 3 files changed, 508 insertions(+), 335 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index b8d64dc..8b00cb0 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -70,7 +70,7 @@
 
 %define		rel		1
 %define		basever		4.7
-%define		postver		.0
+%define		postver		.1
 
 # define this to '-%{basever}' for longterm branch
 %define		versuffix	%{nil}
@@ -119,7 +119,7 @@ Source0:	https://www.kernel.org/pub/linux/kernel/v4.x/linux-%{basever}.tar.xz
 # Source0-md5:	5276563eb1f39a048e4a8a887408c031
 %if "%{postver}" != ".0"
 Patch0:		https://www.kernel.org/pub/linux/kernel/v4.x/patch-%{version}.xz
-# Patch0-md5:	c8ff415734155965ae7a2a85ef9c9e03
+# Patch0-md5:	b87c3627d4c3e3043f46c6422dfd83b0
 %endif
 Source1:	kernel.sysconfig
 
diff --git a/kernel-apparmor.patch b/kernel-apparmor.patch
index 9d10f82..399ae31 100644
--- a/kernel-apparmor.patch
+++ b/kernel-apparmor.patch
@@ -598,28 +598,6 @@ index a689f10..c841b12 100644
  	return 1;
  }
 
-commit 9ad29b2e7820895339f90eb71b411d0134cf1ce9
-Author: John Johansen <john.johansen at canonical.com>
-Date:   Wed Nov 18 11:41:05 2015 -0800
-
-    apparmor: fix ref count leak when profile sha1 hash is read
-    
-    Signed-off-by: John Johansen <john.johansen at canonical.com>
-    Acked-by: Seth Arnold <seth.arnold at canonical.com>
-
-diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
-index 45a6199..0d8dd71 100644
---- a/security/apparmor/apparmorfs.c
-+++ b/security/apparmor/apparmorfs.c
-@@ -331,6 +331,7 @@ static int aa_fs_seq_hash_show(struct seq_file *seq, void *v)
- 			seq_printf(seq, "%.2x", profile->hash[i]);
- 		seq_puts(seq, "\n");
- 	}
-+	aa_put_profile(profile);
- 
- 	return 0;
- }
-
 commit e13f968d154ba9d6a2c4f82f33d3312a63430b54
 Author: John Johansen <john.johansen at canonical.com>
 Date:   Wed Dec 16 18:09:10 2015 -0800
diff --git a/kernel-aufs4.patch b/kernel-aufs4.patch
index 64ad03c..80c6bbf 100644
--- a/kernel-aufs4.patch
+++ b/kernel-aufs4.patch
@@ -1,4 +1,4 @@
-aufs4.x-rcN kbuild patch
+aufs4.7 kbuild patch
 
 diff --git a/fs/Kconfig b/fs/Kconfig
 index b8fcb41..78adefb 100644
@@ -22,7 +22,7 @@ index 85b6e13..e7bb164 100644
  obj-$(CONFIG_EFIVAR_FS)		+= efivarfs/
 +obj-$(CONFIG_AUFS_FS)           += aufs/
 diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
-index 8bdae34..65dbd5f 100644
+index ec10cfe..800211b 100644
 --- a/include/uapi/linux/Kbuild
 +++ b/include/uapi/linux/Kbuild
 @@ -59,6 +59,7 @@ header-y += atmsvc.h
@@ -33,13 +33,13 @@ index 8bdae34..65dbd5f 100644
  header-y += auto_fs4.h
  header-y += auto_fs.h
  header-y += auxvec.h
-aufs4.x-rcN base patch
+aufs4.7 base patch
 
 diff --git a/MAINTAINERS b/MAINTAINERS
-index 952fd2a..6a8f0f8 100644
+index 8c20323..d170184 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -2210,6 +2210,19 @@ F:	include/linux/audit.h
+@@ -2213,6 +2213,19 @@ F:	include/linux/audit.h
  F:	include/uapi/linux/audit.h
  F:	kernel/audit*
  
@@ -265,7 +265,7 @@ index da2751d..2e0fca6 100644
 +			 struct pipe_inode_info *pipe, size_t len,
 +			 unsigned int flags);
  #endif
-aufs4.x-rcN mmap patch
+aufs4.7 mmap patch
 
 diff --git a/fs/proc/base.c b/fs/proc/base.c
 index a11eb71..8f10865 100644
@@ -430,7 +430,7 @@ index 20f3b1f..ee827ce 100644
  	if (page->mapping != inode->i_mapping) {
  		unlock_page(page);
 diff --git a/mm/memory.c b/mm/memory.c
-index cd1f29e..f0c204c 100644
+index 9e04681..06980d1 100644
 --- a/mm/memory.c
 +++ b/mm/memory.c
 @@ -2100,7 +2100,7 @@ static inline int wp_page_reuse(struct mm_struct *mm,
@@ -675,7 +675,7 @@ index 0000000..b323b8a
 +		fput(pr);
 +}
 +#endif /* !CONFIG_MMU */
-aufs4.x-rcN standalone patch
+aufs4.7 standalone patch
 
 diff --git a/fs/dcache.c b/fs/dcache.c
 index c3c0b6d..c99d2d2 100644
@@ -762,7 +762,7 @@ index aa6d071..f336032 100644
  /**
   *	touch_atime	-	update the access time
 diff --git a/fs/namespace.c b/fs/namespace.c
-index 783004a..44abb2d 100644
+index 419f746..9c0e0af 100644
 --- a/fs/namespace.c
 +++ b/fs/namespace.c
 @@ -463,6 +463,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
@@ -773,7 +773,7 @@ index 783004a..44abb2d 100644
  
  /**
   * mnt_drop_write - give up write access to a mount
-@@ -1811,6 +1812,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+@@ -1812,6 +1813,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
  	}
  	return 0;
  }
@@ -2864,8 +2864,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	2016-07-25 19:05:34.811159821 +0200
-@@ -0,0 +1,1406 @@
++++ linux/fs/aufs/branch.c	2016-08-17 18:01:06.095221547 +0200
+@@ -0,0 +1,1409 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -2919,7 +2919,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +
 +	if (br->br_fhsm) {
 +		au_br_fhsm_fin(br->br_fhsm);
-+		kfree(br->br_fhsm);
++		au_delayed_kfree(br->br_fhsm);
 +	}
 +
 +	key = br->br_dykey;
@@ -2933,8 +2933,9 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +	lockdep_off();
 +	path_put(&br->br_path);
 +	lockdep_on();
-+	kfree(wbr);
-+	kfree(br);
++	if (wbr)
++		au_delayed_kfree(wbr);
++	au_delayed_kfree(br);
 +}
 +
 +/*
@@ -3032,11 +3033,12 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +		return add_branch; /* success */
 +
 +out_wbr:
-+	kfree(add_branch->br_wbr);
++	if (add_branch->br_wbr)
++		au_delayed_kfree(add_branch->br_wbr);
 +out_hnotify:
 +	au_hnotify_fin_br(add_branch);
 +out_br:
-+	kfree(add_branch);
++	au_delayed_kfree(add_branch);
 +out:
 +	return ERR_PTR(err);
 +}
@@ -3202,7 +3204,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +	br->br_perm = old_perm;
 +
 +	if (!err && wbr && !au_br_writable(new_perm)) {
-+		kfree(wbr);
++		au_delayed_kfree(wbr);
 +		br->br_wbr = NULL;
 +	}
 +
@@ -4225,7 +4227,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +		if (br->br_wbr) {
 +			err = au_wbr_init(br, sb, mod->perm);
 +			if (unlikely(err)) {
-+				kfree(br->br_wbr);
++				au_delayed_kfree(br->br_wbr);
 +				br->br_wbr = NULL;
 +			}
 +		}
@@ -4237,7 +4239,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +		if (!au_br_fhsm(mod->perm)) {
 +			/* fhsm --> non-fhsm */
 +			au_br_fhsm_fin(br->br_fhsm);
-+			kfree(br->br_fhsm);
++			au_delayed_kfree(br->br_fhsm);
 +			br->br_fhsm = NULL;
 +		}
 +	} else if (au_br_fhsm(mod->perm))
@@ -4249,7 +4251,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
 +	goto out; /* success */
 +
 +out_bf:
-+	kfree(bf);
++	if (bf)
++		au_delayed_kfree(bf);
 +out:
 +	AuTraceErr(err);
 +	return err;
@@ -4629,7 +4632,7 @@ 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	2016-07-25 19:05:34.811159821 +0200
++++ linux/fs/aufs/cpup.c	2016-08-17 18:01:06.095221547 +0200
 @@ -0,0 +1,1383 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -4990,9 +4993,9 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +	dst->f_pos = 0;
 +	err = au_do_copy_file(dst, src, len, buf, blksize);
 +	if (do_kfree)
-+		kfree(buf);
++		au_delayed_kfree(buf);
 +	else
-+		free_page((unsigned long)buf);
++		au_delayed_free_page((unsigned long)buf);
 +
 +out:
 +	return err;
@@ -5152,7 +5155,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +		sym.k[symlen] = 0;
 +		err = vfsub_symlink(h_dir, h_path, sym.k);
 +	}
-+	free_page((unsigned long)sym.k);
++	au_delayed_free_page((unsigned long)sym.k);
 +
 +out:
 +	return err;
@@ -5523,7 +5526,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
 +	}
 +out_parent:
 +	dput(dst_parent);
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	return err;
 +}
@@ -6114,8 +6117,8 @@ 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	2016-07-25 19:05:34.811159821 +0200
-@@ -0,0 +1,432 @@
++++ linux/fs/aufs/dbgaufs.c	2016-08-17 18:01:06.095221547 +0200
+@@ -0,0 +1,435 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -6159,7 +6162,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
 +			      struct file *file)
 +{
-+	kfree(file->private_data);
++	au_delayed_kfree(file->private_data);
 +	return 0;
 +}
 +
@@ -6221,7 +6224,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +static int dbgaufs_plink_release(struct inode *inode __maybe_unused,
 +				 struct file *file)
 +{
-+	free_page((unsigned long)file->private_data);
++	au_delayed_free_page((unsigned long)file->private_data);
 +	return 0;
 +}
 +
@@ -6285,7 +6288,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +	goto out; /* success */
 +
 +out_free:
-+	free_page((unsigned long)p);
++	au_delayed_free_page((unsigned long)p);
 +out:
 +	return err;
 +}
@@ -6412,8 +6415,11 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
 +		br = au_sbr(sb, bindex);
 +		xi = &br->br_xino;
 +		AuDebugOn(xi->xi_dbgaufs);
++		/* debugfs acquires the parent i_mutex */
++		lockdep_off();
 +		xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
 +						     sbinfo, &dbgaufs_xino_fop);
++		lockdep_on();
 +		/* ignore an error */
 +		if (unlikely(!xi->xi_dbgaufs))
 +			AuWarn1("failed %s under debugfs\n", name);
@@ -6602,7 +6608,7 @@ 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	2016-07-25 19:05:34.811159821 +0200
++++ linux/fs/aufs/dcsub.c	2016-08-17 18:01:06.101888388 +0200
 @@ -0,0 +1,224 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -6635,7 +6641,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +	p = dpage->dentries;
 +	for (i = 0; i < dpage->ndentry; i++)
 +		dput(*p++);
-+	free_page((unsigned long)dpage->dentries);
++	au_delayed_free_page((unsigned long)dpage->dentries);
 +}
 +
 +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
@@ -6658,7 +6664,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +	return 0; /* success */
 +
 +out_dpages:
-+	kfree(dpages->dpages);
++	au_delayed_kfree(dpages->dpages);
 +out:
 +	return err;
 +}
@@ -6671,7 +6677,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
 +	p = dpages->dpages;
 +	for (i = 0; i < dpages->ndpage; i++)
 +		au_dpage_free(p++);
-+	kfree(dpages->dpages);
++	au_delayed_kfree(dpages->dpages);
 +}
 +
 +static int au_dpages_append(struct au_dcsub_pages *dpages,
@@ -6970,8 +6976,8 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
 +#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	2016-07-25 19:05:34.811159821 +0200
-@@ -0,0 +1,441 @@
++++ linux/fs/aufs/debug.c	2016-08-17 18:01:06.101888388 +0200
+@@ -0,0 +1,440 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -7310,7 +7316,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 +	au_br_count_init(&a->fake);
 +	err = do_pri_br(-1, &a->fake);
 +	au_br_count_fin(&a->fake);
-+	kfree(a);
++	au_delayed_kfree(a);
 +	dpri("dev 0x%x\n", sb->s_dev);
 +	if (err || !au_test_aufs(sb))
 +		return;
@@ -7318,9 +7324,8 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
 +	sbinfo = au_sbi(sb);
 +	if (!sbinfo)
 +		return;
-+	dpri("nw %lld, gen %u, kobj %d\n",
-+	     percpu_counter_sum(&sbinfo->si_nowait.nw_len),
-+	     sbinfo->si_generation,
++	dpri("nw %d, gen %u, kobj %d\n",
++	     atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
 +	     atomic_read(&sbinfo->si_kobj.kref.refcount));
 +	for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++)
 +		do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
@@ -7644,7 +7649,7 @@ 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	2016-07-25 19:05:34.811159821 +0200
++++ linux/fs/aufs/dentry.c	2016-08-17 18:01:06.111888648 +0200
 @@ -0,0 +1,1128 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -7862,7 +7867,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
 +
 +out_parent:
 +	dput(parent);
-+	kfree(whname.name);
++	au_delayed_kfree(whname.name);
 +out:
 +	return err;
 +}
@@ -8776,8 +8781,8 @@ 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	2016-07-25 19:05:34.811159821 +0200
-@@ -0,0 +1,252 @@
++++ linux/fs/aufs/dentry.h	2016-08-17 18:01:06.111888648 +0200
+@@ -0,0 +1,255 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -8818,7 +8823,10 @@ diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
 +	struct au_rwsem		di_rwsem;
 +	aufs_bindex_t		di_btop, di_bbot, di_bwh, di_bdiropq;
 +	unsigned char		di_tmpfile; /* to allow the different name */
-+	struct au_hdentry	*di_hdentry;
++	union {
++		struct au_hdentry	*di_hdentry;
++		struct llist_node	di_lnode;	/* delayed free */
++	};
 +} ____cacheline_aligned_in_smp;
 +
 +/* ---------------------------------------------------------------------- */
@@ -9032,7 +9040,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	2016-07-25 19:05:34.811159821 +0200
++++ linux/fs/aufs/dinfo.c	2016-08-17 18:01:06.111888648 +0200
 @@ -0,0 +1,552 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -9089,7 +9097,7 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
 +		goto out;
 +	}
 +
-+	au_cache_free_dinfo(dinfo);
++	au_cache_dfree_dinfo(dinfo);
 +	dinfo = NULL;
 +
 +out:
@@ -9109,8 +9117,8 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
 +		while (bindex++ <= bbot)
 +			au_hdput(p++);
 +	}
-+	kfree(dinfo->di_hdentry);
-+	au_cache_free_dinfo(dinfo);
++	au_delayed_kfree(dinfo->di_hdentry);
++	au_cache_dfree_dinfo(dinfo);
 +}
 +
 +void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
@@ -9588,8 +9596,8 @@ 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	2016-07-25 19:05:34.811159821 +0200
-@@ -0,0 +1,756 @@
++++ linux/fs/aufs/dir.c	2016-08-17 18:01:06.111888648 +0200
+@@ -0,0 +1,762 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -9748,7 +9756,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +out:
 +	dput(a->dentry);
 +	au_nwt_done(&au_sbi(sb)->si_nowait);
-+	kfree(arg);
++	au_delayed_kfree(arg);
 +}
 +
 +void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
@@ -9784,7 +9792,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +	if (unlikely(wkq_err)) {
 +		pr_err("wkq %d\n", wkq_err);
 +		dput(dentry);
-+		kfree(arg);
++		au_delayed_kfree(arg);
 +	}
 +
 +out:
@@ -9903,7 +9911,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +		};
 +		err = au_do_open(file, &args);
 +		if (unlikely(err))
-+			kfree(fidir);
++			au_delayed_kfree(fidir);
 +	}
 +	si_read_unlock(sb);
 +	return err;
@@ -9915,8 +9923,11 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +	struct au_vdir *vdir_cache;
 +	struct au_finfo *finfo;
 +	struct au_fidir *fidir;
++	struct au_hfile *hf;
 +	aufs_bindex_t bindex, bbot;
++	int execed, delayed;
 +
++	delayed = (current->flags & PF_KTHREAD) || in_interrupt();
 +	finfo = au_fi(file);
 +	fidir = finfo->fi_hdir;
 +	if (fidir) {
@@ -9924,22 +9935,25 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
 +			    &au_sbi(file->f_path.dentry->d_sb)->si_files);
 +		vdir_cache = fidir->fd_vdir_cache; /* lock-free */
 +		if (vdir_cache)
-+			au_vdir_free(vdir_cache);
++			au_vdir_free(vdir_cache, delayed);
 +
 +		bindex = finfo->fi_btop;
 +		if (bindex >= 0) {
++			execed = vfsub_file_execed(file);
++			hf = fidir->fd_hfile + bindex;
 +			/*
 +			 * calls fput() instead of filp_close(),
 +			 * since no dnotify or lock for the lower file.
 +			 */
 +			bbot = fidir->fd_bbot;
-+			for (; bindex <= bbot; bindex++)
-+				au_set_h_fptr(file, bindex, NULL);
++			for (; bindex <= bbot; bindex++, hf++)
++				if (hf->hf_file)
++					au_hfput(hf, execed);
 +		}
-+		kfree(fidir);
++		au_delayed_kfree(fidir);
 +		finfo->fi_hdir = NULL;
 +	}
-+	au_finfo_fin(file);
++	au_finfo_fin(file, delayed);
 +	return 0;
 +}
 +
@@ -10348,8 +10362,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	2016-07-25 19:05:34.811159821 +0200
-@@ -0,0 +1,131 @@
++++ linux/fs/aufs/dir.h	2016-08-17 18:01:06.111888648 +0200
+@@ -0,0 +1,137 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -10394,7 +10408,10 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
 +
 +struct au_vdir_dehstr {
 +	struct hlist_node	hash;
-+	struct au_vdir_destr	*str;
++	union {
++		struct au_vdir_destr	*str;
++		struct llist_node	lnode;	/* delayed free */
++	};
 +} ____cacheline_aligned_in_smp;
 +
 +struct au_vdir_de {
@@ -10432,7 +10449,10 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
 +
 +	unsigned long	vd_version;
 +	unsigned int	vd_deblk_sz;
-+	unsigned long	vd_jiffy;
++	union {
++		unsigned long		vd_jiffy;
++		struct llist_node	vd_lnode;	/* delayed free */
++	};
 +} ____cacheline_aligned_in_smp;
 +
 +/* ---------------------------------------------------------------------- */
@@ -10456,7 +10476,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
 +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
 +		       unsigned int d_type, aufs_bindex_t bindex,
 +		       unsigned char shwh);
-+void au_vdir_free(struct au_vdir *vdir);
++void au_vdir_free(struct au_vdir *vdir, int atonce);
 +int au_vdir_init(struct file *file);
 +int au_vdir_fill_de(struct file *file, struct dir_context *ctx);
 +
@@ -10483,7 +10503,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	2016-07-25 19:05:34.811159821 +0200
++++ linux/fs/aufs/dynop.c	2016-08-17 18:01:21.295617591 +0200
 @@ -0,0 +1,369 @@
 +/*
 + * Copyright (C) 2010-2016 Junjiro R. Okajima
@@ -10514,17 +10534,17 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 + * How large will these lists be?
 + * Usually just a few elements, 20-30 at most for each, I guess.
 + */
-+static struct au_splhead dynop[AuDyLast];
++static struct au_sphlhead dynop[AuDyLast];
 +
-+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
++static struct au_dykey *dy_gfind_get(struct au_sphlhead *sphl, const void *h_op)
 +{
 +	struct au_dykey *key, *tmp;
-+	struct list_head *head;
++	struct hlist_head *head;
 +
 +	key = NULL;
-+	head = &spl->head;
++	head = &sphl->head;
 +	rcu_read_lock();
-+	list_for_each_entry_rcu(tmp, head, dk_list)
++	hlist_for_each_entry_rcu(tmp, head, dk_hnode)
 +		if (tmp->dk_op.dy_hop == h_op) {
 +			key = tmp;
 +			kref_get(&key->dk_kref);
@@ -10571,24 +10591,24 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +}
 +
 +/* kref_get() if @key is already added */
-+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
++static struct au_dykey *dy_gadd(struct au_sphlhead *sphl, struct au_dykey *key)
 +{
 +	struct au_dykey *tmp, *found;
-+	struct list_head *head;
++	struct hlist_head *head;
 +	const void *h_op = key->dk_op.dy_hop;
 +
 +	found = NULL;
-+	head = &spl->head;
-+	spin_lock(&spl->spin);
-+	list_for_each_entry(tmp, head, dk_list)
++	head = &sphl->head;
++	spin_lock(&sphl->spin);
++	hlist_for_each_entry(tmp, head, dk_hnode)
 +		if (tmp->dk_op.dy_hop == h_op) {
 +			kref_get(&tmp->dk_kref);
 +			found = tmp;
 +			break;
 +		}
 +	if (!found)
-+		list_add_rcu(&key->dk_list, head);
-+	spin_unlock(&spl->spin);
++		hlist_add_head_rcu(&key->dk_hnode, head);
++	spin_unlock(&sphl->spin);
 +
 +	if (!found)
 +		DyPrSym(key);
@@ -10601,17 +10621,17 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +
 +	key = container_of(rcu, struct au_dykey, dk_rcu);
 +	DyPrSym(key);
-+	kfree(key);
++	kfree(key);	/* not delayed */
 +}
 +
 +static void dy_free(struct kref *kref)
 +{
 +	struct au_dykey *key;
-+	struct au_splhead *spl;
++	struct au_sphlhead *sphl;
 +
 +	key = container_of(kref, struct au_dykey, dk_kref);
-+	spl = dynop + key->dk_op.dy_type;
-+	au_spl_del_rcu(&key->dk_list, spl);
++	sphl = dynop + key->dk_op.dy_type;
++	au_sphl_del_rcu(&key->dk_hnode, sphl);
 +	call_rcu(&key->dk_rcu, dy_free_rcu);
 +}
 +
@@ -10696,7 +10716,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
 +{
 +	struct au_dykey *key, *old;
-+	struct au_splhead *spl;
++	struct au_sphlhead *sphl;
 +	struct op {
 +		unsigned int sz;
 +		void (*set)(struct au_dykey *key, const void *h_op,
@@ -10710,8 +10730,8 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +	};
 +	const struct op *p;
 +
-+	spl = dynop + op->dy_type;
-+	key = dy_gfind_get(spl, op->dy_hop);
++	sphl = dynop + op->dy_type;
++	key = dy_gfind_get(sphl, op->dy_hop);
 +	if (key)
 +		goto out_add; /* success */
 +
@@ -10725,9 +10745,9 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +	key->dk_op.dy_hop = op->dy_hop;
 +	kref_init(&key->dk_kref);
 +	p->set(key, op->dy_hop, au_br_sb(br));
-+	old = dy_gadd(spl, key);
++	old = dy_gadd(sphl, key);
 +	if (old) {
-+		kfree(key);
++		au_delayed_kfree(key);
 +		key = old;
 +	}
 +
@@ -10822,16 +10842,16 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +
 +void au_dy_arefresh(int do_dx)
 +{
-+	struct au_splhead *spl;
-+	struct list_head *head;
++	struct au_sphlhead *sphl;
++	struct hlist_head *head;
 +	struct au_dykey *key;
 +
-+	spl = dynop + AuDy_AOP;
-+	head = &spl->head;
-+	spin_lock(&spl->spin);
-+	list_for_each_entry(key, head, dk_list)
++	sphl = dynop + AuDy_AOP;
++	head = &sphl->head;
++	spin_lock(&sphl->spin);
++	hlist_for_each_entry(key, head, dk_hnode)
 +		dy_adx((void *)key, do_dx);
-+	spin_unlock(&spl->spin);
++	spin_unlock(&sphl->spin);
 +}
 +
 +/* ---------------------------------------------------------------------- */
@@ -10844,7 +10864,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +	BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
 +
 +	for (i = 0; i < AuDyLast; i++)
-+		au_spl_init(dynop + i);
++		au_sphl_init(dynop + i);
 +}
 +
 +void au_dy_fin(void)
@@ -10852,11 +10872,11 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
 +	int i;
 +
 +	for (i = 0; i < AuDyLast; i++)
-+		WARN_ON(!list_empty(&dynop[i].head));
++		WARN_ON(!hlist_empty(&dynop[i].head));
 +}
 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	2016-07-25 19:05:34.811159821 +0200
++++ linux/fs/aufs/dynop.h	2016-08-17 18:01:06.118555489 +0200
 @@ -0,0 +1,74 @@
 +/*
 + * Copyright (C) 2010-2016 Junjiro R. Okajima
@@ -10899,7 +10919,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
 +
 +struct au_dykey {
 +	union {
-+		struct list_head	dk_list;
++		struct hlist_node	dk_hnode;
 +		struct rcu_head		dk_rcu;
 +	};
 +	struct au_dynop		dk_op;
@@ -10934,7 +10954,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	2016-07-25 19:05:34.811159821 +0200
++++ linux/fs/aufs/export.c	2016-08-17 18:01:06.128555749 +0200
 @@ -0,0 +1,837 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -11355,7 +11375,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +	}
 +
 +out_name:
-+	free_page((unsigned long)arg.name);
++	au_delayed_free_page((unsigned long)arg.name);
 +out_file:
 +	fput(file);
 +out:
@@ -11509,7 +11529,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
 +			dentry = ERR_PTR(-ESTALE);
 +		}
 +out_pathname:
-+	free_page((unsigned long)pathname);
++	au_delayed_free_page((unsigned long)pathname);
 +out_h_parent:
 +	dput(h_parent);
 +out:
@@ -12205,8 +12225,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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,843 @@
++++ linux/fs/aufs/file.c	2016-08-17 18:01:21.295617591 +0200
+@@ -0,0 +1,845 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -12482,7 +12502,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +	}
 +	if (unlikely(err)) {
 +		finfo->fi_hdir = NULL;
-+		au_finfo_fin(file);
++		au_finfo_fin(file, /*atonce*/0);
 +	}
 +
 +out:
@@ -12802,6 +12822,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +
 +static void au_do_refresh_dir(struct file *file)
 +{
++	int execed;
 +	aufs_bindex_t bindex, bbot, new_bindex, brid;
 +	struct au_hfile *p, tmp, *q;
 +	struct au_finfo *finfo;
@@ -12840,6 +12861,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
 +		}
 +	}
 +
++	execed = vfsub_file_execed(file);
 +	p = fidir->fd_hfile;
 +	if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) {
 +		bbot = au_sbbot(sb);
@@ -12848,14 +12870,14 @@ 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;
-+				au_hfput(p, file);
++				au_hfput(p, execed);
 +			}
 +	} else {
 +		bbot = au_br_index(sb, brid);
 +		for (finfo->fi_btop = 0; finfo->fi_btop < bbot;
 +		     finfo->fi_btop++, p++)
 +			if (p->hf_file)
-+				au_hfput(p, file);
++				au_hfput(p, execed);
 +		bbot = au_sbbot(sb);
 +	}
 +
@@ -12865,7 +12887,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;
-+			au_hfput(p, file);
++			au_hfput(p, execed);
 +		}
 +	AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
 +}
@@ -13052,8 +13074,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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,291 @@
++++ linux/fs/aufs/file.h	2016-08-17 18:01:06.135222590 +0200
+@@ -0,0 +1,294 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -13119,7 +13141,10 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
 +	struct au_fidir		*fi_hdir;	/* for dir only */
 +
 +	struct hlist_node	fi_hlist;
-+	struct file		*fi_file;	/* very ugly */
++	union {
++		struct file		*fi_file;	/* very ugly */
++		struct llist_node	fi_lnode;	/* delayed free */
++	};
 +} ____cacheline_aligned_in_smp;
 +
 +/* ---------------------------------------------------------------------- */
@@ -13170,7 +13195,7 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
 +struct file *au_read_pre(struct file *file, int keep_fi);
 +
 +/* finfo.c */
-+void au_hfput(struct au_hfile *hf, struct file *file);
++void au_hfput(struct au_hfile *hf, int execed);
 +void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
 +		   struct file *h_file);
 +
@@ -13179,7 +13204,7 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
 +int au_fidir_realloc(struct au_finfo *finfo, int nbr);
 +
 +void au_fi_init_once(void *_fi);
-+void au_finfo_fin(struct file *file);
++void au_finfo_fin(struct file *file, int atonce);
 +int au_finfo_init(struct file *file, struct au_fidir *fidir);
 +
 +/* ioctl.c */
@@ -13347,8 +13372,8 @@ 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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,149 @@
++++ linux/fs/aufs/finfo.c	2016-08-17 18:01:06.135222590 +0200
+@@ -0,0 +1,151 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -13372,10 +13397,9 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 +
 +#include "aufs.h"
 +
-+void au_hfput(struct au_hfile *hf, struct file *file)
++void au_hfput(struct au_hfile *hf, int execed)
 +{
-+	/* todo: direct access f_flags */
-+	if (vfsub_file_flags(file) & __FMODE_EXEC)
++	if (execed)
 +		allow_write_access(hf->hf_file);
 +	fput(hf->hf_file);
 +	hf->hf_file = NULL;
@@ -13397,7 +13421,7 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 +		hf = fidir->fd_hfile + bindex;
 +
 +	if (hf && hf->hf_file)
-+		au_hfput(hf, file);
++		au_hfput(hf, vfsub_file_execed(file));
 +	if (val) {
 +		FiMustWriteLock(file);
 +		AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
@@ -13454,7 +13478,7 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 +
 +/* ---------------------------------------------------------------------- */
 +
-+void au_finfo_fin(struct file *file)
++void au_finfo_fin(struct file *file, int atonce)
 +{
 +	struct au_finfo *finfo;
 +
@@ -13463,7 +13487,10 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
 +	finfo = au_fi(file);
 +	AuDebugOn(finfo->fi_hdir);
 +	AuRwDestroy(&finfo->fi_rwsem);
-+	au_cache_free_finfo(finfo);
++	if (!atonce)
++		au_cache_dfree_finfo(finfo);
++	else
++		au_cache_free_finfo(finfo);
 +}
 +
 +void au_fi_init_once(void *_finfo)
@@ -13500,8 +13527,8 @@ 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	2016-07-25 19:05:34.811159821 +0200
-@@ -0,0 +1,770 @@
++++ linux/fs/aufs/f_op.c	2016-08-17 18:01:06.135222590 +0200
+@@ -0,0 +1,772 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -13603,6 +13630,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +{
 +	struct au_finfo *finfo;
 +	aufs_bindex_t bindex;
++	int delayed;
 +
 +	finfo = au_fi(file);
 +	au_sphl_del(&finfo->fi_hlist,
@@ -13611,7 +13639,8 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
 +	if (bindex >= 0)
 +		au_set_h_fptr(file, bindex, NULL);
 +
-+	au_finfo_fin(file);
++	delayed = (current->flags & PF_KTHREAD) || in_interrupt();
++	au_finfo_fin(file, delayed);
 +	return 0;
 +}
 +
@@ -14274,7 +14303,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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/fstype.h	2016-08-17 18:01:06.145222850 +0200
 @@ -0,0 +1,400 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -14319,7 +14348,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
++#if IS_ENABLED(CONFIG_ISO9660_FS)
 +	return sb->s_magic == ISOFS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14328,7 +14357,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_romfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
++#if IS_ENABLED(CONFIG_ROMFS_FS)
 +	return sb->s_magic == ROMFS_MAGIC;
 +#else
 +	return 0;
@@ -14337,7 +14366,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
++#if IS_ENABLED(CONFIG_CRAMFS)
 +	return sb->s_magic == CRAMFS_MAGIC;
 +#endif
 +	return 0;
@@ -14345,7 +14374,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_nfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
++#if IS_ENABLED(CONFIG_NFS_FS)
 +	return sb->s_magic == NFS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14354,7 +14383,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_fuse(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
++#if IS_ENABLED(CONFIG_FUSE_FS)
 +	return sb->s_magic == FUSE_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14363,7 +14392,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_xfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
++#if IS_ENABLED(CONFIG_XFS_FS)
 +	return sb->s_magic == XFS_SB_MAGIC;
 +#else
 +	return 0;
@@ -14381,7 +14410,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
++#if IS_ENABLED(CONFIG_ECRYPT_FS)
 +	return !strcmp(au_sbtype(sb), "ecryptfs");
 +#else
 +	return 0;
@@ -14395,7 +14424,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
++#if IS_ENABLED(CONFIG_UBIFS_FS)
 +	return sb->s_magic == UBIFS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14422,7 +14451,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_configfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
++#if IS_ENABLED(CONFIG_CONFIGFS_FS)
 +	return sb->s_magic == CONFIGFS_MAGIC;
 +#else
 +	return 0;
@@ -14431,7 +14460,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_minix(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
++#if IS_ENABLED(CONFIG_MINIX_FS)
 +	return sb->s_magic == MINIX3_SUPER_MAGIC
 +		|| sb->s_magic == MINIX2_SUPER_MAGIC
 +		|| sb->s_magic == MINIX2_SUPER_MAGIC2
@@ -14444,7 +14473,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_fat(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
++#if IS_ENABLED(CONFIG_FAT_FS)
 +	return sb->s_magic == MSDOS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14472,7 +14501,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
++#if IS_ENABLED(CONFIG_SQUASHFS)
 +	return sb->s_magic == SQUASHFS_MAGIC;
 +#else
 +	return 0;
@@ -14481,7 +14510,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
++#if IS_ENABLED(CONFIG_BTRFS_FS)
 +	return sb->s_magic == BTRFS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14490,7 +14519,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
++#if IS_ENABLED(CONFIG_XENFS)
 +	return sb->s_magic == XENFS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14508,7 +14537,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
++#if IS_ENABLED(CONFIG_NILFS)
 +	return sb->s_magic == NILFS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14517,7 +14546,7 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
 +
 +static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
 +{
-+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
++#if IS_ENABLED(CONFIG_HFSPLUS_FS)
 +	return sb->s_magic == HFSPLUS_SUPER_MAGIC;
 +#else
 +	return 0;
@@ -14678,7 +14707,7 @@ 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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/hfsnotify.c	2016-08-17 18:01:06.145222850 +0200
 @@ -0,0 +1,287 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -14714,7 +14743,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
 +	struct au_hnotify *hn = container_of(mark, struct au_hnotify,
 +					     hn_mark);
 +	/* AuDbg("here\n"); */
-+	au_cache_free_hnotify(hn);
++	au_cache_dfree_hnotify(hn);
 +	smp_mb__before_atomic();
 +	if (atomic64_dec_and_test(&au_hfsn_ifree))
 +		wake_up(&au_hfsn_wq);
@@ -14838,7 +14867,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
 +	struct au_br_hfsnotify *hfsn = group->private;
 +
 +	/* AuDbg("here\n"); */
-+	kfree(hfsn);
++	au_delayed_kfree(hfsn);
 +}
 +
 +static int au_hfsn_handle_event(struct fsnotify_group *group,
@@ -14932,7 +14961,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
 +	goto out; /* success */
 +
 +out_hfsn:
-+	kfree(hfsn);
++	au_delayed_kfree(hfsn);
 +out:
 +	return err;
 +}
@@ -15029,8 +15058,8 @@ 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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,710 @@
++++ linux/fs/aufs/hnotify.c	2016-08-17 18:01:06.148556271 +0200
+@@ -0,0 +1,723 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -15068,7 +15097,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +		AuTraceErr(err);
 +		if (unlikely(err)) {
 +			hinode->hi_notify = NULL;
-+			au_cache_free_hnotify(hn);
++			au_cache_dfree_hnotify(hn);
 +			/*
 +			 * The upper dir was removed by udba, but the same named
 +			 * dir left. In this case, aufs assignes a new inode
@@ -15092,7 +15121,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +	if (hn) {
 +		hinode->hi_notify = NULL;
 +		if (au_hnotify_op.free(hinode, hn))
-+			au_cache_free_hnotify(hn);
++			au_cache_dfree_hnotify(hn);
 +	}
 +}
 +
@@ -15526,7 +15555,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +		|| au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
 +		inode = lookup_wlock_by_ino(sb, bfound, h_ino);
 +		try_iput = 1;
-+	    }
++	}
 +
 +	args.flags = a->flags[AuHn_CHILD];
 +	args.dentry = dentry;
@@ -15565,7 +15594,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +	iput(a->dir);
 +	si_write_unlock(sb);
 +	au_nwt_done(&sbinfo->si_nowait);
-+	kfree(a);
++	au_delayed_kfree(a);
 +}
 +
 +/* ---------------------------------------------------------------------- */
@@ -15671,7 +15700,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +		iput(args->h_child_inode);
 +		iput(args->h_dir);
 +		iput(args->dir);
-+		kfree(args);
++		au_delayed_kfree(args);
 +	}
 +
 +out:
@@ -15712,17 +15741,26 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +
 +static void au_hn_destroy_cache(void)
 +{
-+	kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
-+	au_cachep[AuCache_HNOTIFY] = NULL;
++	struct au_cache *cp;
++
++	flush_delayed_work(&au_dfree.dwork);
++	cp = au_dfree.cache + AuCache_HNOTIFY;
++	AuDebugOn(!llist_empty(&cp->llist));
++	kmem_cache_destroy(cp->cache);
++	cp->cache = NULL;
 +}
 +
++AU_CACHE_DFREE_FUNC(hnotify, HNOTIFY, hn_lnode);
++
 +int __init au_hnotify_init(void)
 +{
 +	int err;
++	struct au_cache *cp;
 +
 +	err = -ENOMEM;
-+	au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
-+	if (au_cachep[AuCache_HNOTIFY]) {
++	cp = au_dfree.cache + AuCache_HNOTIFY;
++	cp->cache = AuCache(au_hnotify);
++	if (cp->cache) {
 +		err = 0;
 +		if (au_hnotify_op.init)
 +			err = au_hnotify_op.init();
@@ -15735,15 +15773,19 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
 +
 +void au_hnotify_fin(void)
 +{
++	struct au_cache *cp;
++
 +	if (au_hnotify_op.fin)
 +		au_hnotify_op.fin();
++
 +	/* cf. au_cache_fin() */
-+	if (au_cachep[AuCache_HNOTIFY])
++	cp = au_dfree.cache + AuCache_HNOTIFY;
++	if (cp->cache)
 +		au_hn_destroy_cache();
 +}
 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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/iinfo.c	2016-08-17 18:01:06.148556271 +0200
 @@ -0,0 +1,284 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -16014,7 +16056,7 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
 +
 +	iinfo = au_ii(inode);
 +	if (iinfo->ii_vdir)
-+		au_vdir_free(iinfo->ii_vdir);
++		au_vdir_free(iinfo->ii_vdir, /*atonce*/0);
 +
 +	bindex = iinfo->ii_btop;
 +	if (bindex >= 0) {
@@ -16026,7 +16068,7 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
 +			hi++;
 +		}
 +	}
-+	kfree(iinfo->ii_hinode);
++	au_delayed_kfree(iinfo->ii_hinode);
 +	AuRwDestroy(&iinfo->ii_rwsem);
 +}
 diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
@@ -16552,8 +16594,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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,694 @@
++++ linux/fs/aufs/inode.h	2016-08-17 18:01:06.151889691 +0200
+@@ -0,0 +1,700 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -16591,7 +16633,10 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
 +	/* never use fsnotify_add_vfsmount_mark() */
 +	struct fsnotify_mark		hn_mark;
 +#endif
-+	struct inode			*hn_aufs_inode;	/* no get/put */
++	union {
++		struct inode		*hn_aufs_inode;	/* no get/put */
++		struct llist_node	hn_lnode;	/* delayed free */
++	};
 +#endif
 +} ____cacheline_aligned_in_smp;
 +
@@ -16634,7 +16679,10 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
 +struct au_icntnr {
 +	struct au_iinfo iinfo;
 +	struct inode vfs_inode;
-+	struct hlist_node plink;
++	union {
++		struct hlist_node	plink;
++		struct llist_node	lnode;	/* delayed free */
++	};
 +} ____cacheline_aligned_in_smp;
 +
 +/* au_pin flags */
@@ -17473,7 +17521,7 @@ 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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/i_op_add.c	2016-08-17 18:01:06.148556271 +0200
 @@ -0,0 +1,924 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -17822,7 +17870,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +	if (!try_aopen)
 +		aufs_read_unlock(dentry, AuLock_DW);
 +out_free:
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	return err;
 +}
@@ -18286,7 +18334,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +	}
 +	aufs_read_and_write_unlock2(dentry, src_dentry);
 +out_kfree:
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	AuTraceErr(err);
 +	return err;
@@ -18395,14 +18443,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
 +	}
 +	aufs_read_unlock(dentry, AuLock_DW);
 +out_free:
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	return err;
 +}
 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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,1414 @@
++++ linux/fs/aufs/i_op.c	2016-08-17 18:01:06.148556271 +0200
+@@ -0,0 +1,1413 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -18686,8 +18734,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +{
 +	int err, h_opened = *opened;
 +	unsigned int lkup_flags;
-+	struct dentry *parent;
-+	struct dentry *d;
++	struct dentry *parent, *d;
 +	struct au_sphlhead *aopen;
 +	struct vfsub_aopen_args args = {
 +		.open_flag	= open_flag,
@@ -18782,10 +18829,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +	di_write_unlock(parent);
 +	aufs_read_unlock(dentry, AuLock_DW);
 +	AuDbgDentry(dentry);
-+	if (unlikely(err))
++	if (unlikely(err < 0))
 +		goto out;
 +out_no_open:
-+	if (!err && !(*opened & FILE_CREATED)) {
++	if (err >= 0 && !(*opened & FILE_CREATED)) {
 +		AuLabel(out_no_open);
 +		dget(dentry);
 +		err = finish_no_open(file, dentry);
@@ -19399,7 +19446,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +out_si:
 +	si_read_unlock(sb);
 +out_kfree:
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	AuTraceErr(err);
 +	return err;
@@ -19492,7 +19539,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +	di_write_unlock(dentry);
 +	si_read_unlock(sb);
 +out_kfree:
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	AuTraceErr(err);
 +	return err;
@@ -19819,7 +19866,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
 +};
 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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/i_op_del.c	2016-08-17 18:01:06.148556271 +0200
 @@ -0,0 +1,511 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -20217,7 +20264,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +out_unlock:
 +	aufs_read_unlock(dentry, AuLock_DW);
 +out_free:
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	return err;
 +}
@@ -20327,14 +20374,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
 +out_unlock:
 +	aufs_read_unlock(dentry, AuLock_DW);
 +out_free:
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	AuTraceErr(err);
 +	return err;
 +}
 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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/i_op_ren.c	2016-08-17 18:01:06.148556271 +0200
 @@ -0,0 +1,1015 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -21346,7 +21393,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
 +	iput(a->dst_inode);
 +	if (a->thargs)
 +		au_whtmp_rmdir_free(a->thargs);
-+	kfree(a);
++	au_delayed_kfree(a);
 +out:
 +	AuTraceErr(err);
 +	return err;
@@ -21542,7 +21589,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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/loop.c	2016-08-17 18:01:06.151889691 +0200
 @@ -0,0 +1,146 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -21688,7 +21735,7 @@ diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
 +{
 +	if (backing_file_func)
 +		symbol_put(loop_backing_file);
-+	kfree(au_warn_loopback_array);
++	au_delayed_kfree(au_warn_loopback_array);
 +}
 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
@@ -21830,8 +21877,8 @@ 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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,223 @@
++++ linux/fs/aufs/module.c	2016-08-17 18:01:06.151889691 +0200
+@@ -0,0 +1,289 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -21869,17 +21916,64 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +}
 +
 +/* ---------------------------------------------------------------------- */
-+
 +/*
 + * aufs caches
 + */
-+struct kmem_cache *au_cachep[AuCache_Last] = {
-+	[0] = NULL
-+};
++
++struct au_dfree au_dfree;
++
++/* delayed free */
++static void au_do_dfree(struct work_struct *work __maybe_unused)
++{
++	struct llist_head *head;
++	struct llist_node *node, *next;
++
++#define AU_CACHE_DFREE_DO_BODY(name, idx, lnode) do {			\
++		head = &au_dfree.cache[AuCache_##idx].llist;		\
++		node = llist_del_all(head);				\
++		for (; node; node = next) {				\
++			struct au_##name *p =				\
++				p = llist_entry(node, struct au_##name,	\
++						lnode);			\
++			next = llist_next(node);			\
++			au_cache_free_##name(p);			\
++		}							\
++	} while (0)
++
++	AU_CACHE_DFREE_DO_BODY(dinfo, DINFO, di_lnode);
++	AU_CACHE_DFREE_DO_BODY(icntnr, ICNTNR, lnode);
++	AU_CACHE_DFREE_DO_BODY(finfo, FINFO, fi_lnode);
++	AU_CACHE_DFREE_DO_BODY(vdir, VDIR, vd_lnode);
++	AU_CACHE_DFREE_DO_BODY(vdir_dehstr, DEHSTR, lnode);
++#ifdef CONFIG_AUFS_HNOTIFY
++	AU_CACHE_DFREE_DO_BODY(hnotify, HNOTIFY, hn_lnode);
++#endif
++
++#define AU_DFREE_DO_BODY(llist, func) do {		\
++		node = llist_del_all(llist);		\
++		for (; node; node = next) {		\
++			next = llist_next(node);	\
++			func(node);			\
++		}					\
++	} while (0)
++
++	AU_DFREE_DO_BODY(au_dfree.llist + AU_DFREE_KFREE, kfree);
++	AU_DFREE_DO_BODY(au_dfree.llist + AU_DFREE_FREE_PAGE, au_free_page);
++
++#undef AU_CACHE_DFREE_DO_BODY
++#undef AU_DFREE_DO_BODY
++}
++
++AU_CACHE_DFREE_FUNC(dinfo, DINFO, di_lnode);
++AU_CACHE_DFREE_FUNC(icntnr, ICNTNR, lnode);
++AU_CACHE_DFREE_FUNC(finfo, FINFO, fi_lnode);
++AU_CACHE_DFREE_FUNC(vdir, VDIR, vd_lnode);
++AU_CACHE_DFREE_FUNC(vdir_dehstr, DEHSTR, lnode);
 +
 +static void au_cache_fin(void)
 +{
 +	int i;
++	struct au_cache *cp;
 +
 +	/*
 +	 * Make sure all delayed rcu free inodes are flushed before we
@@ -21889,27 +21983,33 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +
 +	/* excluding AuCache_HNOTIFY */
 +	BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
++	flush_delayed_work(&au_dfree.dwork);
 +	for (i = 0; i < AuCache_HNOTIFY; i++) {
-+		kmem_cache_destroy(au_cachep[i]);
-+		au_cachep[i] = NULL;
++		cp = au_dfree.cache + i;
++		AuDebugOn(!llist_empty(&cp->llist));
++		kmem_cache_destroy(cp->cache);
++		cp->cache = NULL;
 +	}
 +}
 +
 +static int __init au_cache_init(void)
 +{
-+	au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
-+	if (au_cachep[AuCache_DINFO])
++	struct au_cache *cp;
++
++	cp = au_dfree.cache;
++	cp[AuCache_DINFO].cache = AuCacheCtor(au_dinfo, au_di_init_once);
++	if (cp[AuCache_DINFO].cache)
 +		/* SLAB_DESTROY_BY_RCU */
-+		au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
-+							au_icntnr_init_once);
-+	if (au_cachep[AuCache_ICNTNR])
-+		au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
-+						       au_fi_init_once);
-+	if (au_cachep[AuCache_FINFO])
-+		au_cachep[AuCache_VDIR] = AuCache(au_vdir);
-+	if (au_cachep[AuCache_VDIR])
-+		au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
-+	if (au_cachep[AuCache_DEHSTR])
++		cp[AuCache_ICNTNR].cache = AuCacheCtor(au_icntnr,
++						       au_icntnr_init_once);
++	if (cp[AuCache_ICNTNR].cache)
++		cp[AuCache_FINFO].cache = AuCacheCtor(au_finfo,
++						      au_fi_init_once);
++	if (cp[AuCache_FINFO].cache)
++		cp[AuCache_VDIR].cache = AuCache(au_vdir);
++	if (cp[AuCache_VDIR].cache)
++		cp[AuCache_DEHSTR].cache = AuCache(au_vdir_dehstr);
++	if (cp[AuCache_DEHSTR].cache)
 +		return 0;
 +
 +	au_cache_fin();
@@ -21972,6 +22072,7 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +{
 +	int err, i;
 +	char *p;
++	struct au_cache *cp;
 +
 +	p = au_esc_chars;
 +	for (i = 1; i <= ' '; i++)
@@ -21986,6 +22087,16 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +	for (i = 0; i < AuIop_Last; i++)
 +		aufs_iop_nogetattr[i].getattr = NULL;
 +
++	/* First, initialize au_dfree */
++	for (i = 0; i < AuCache_Last; i++) {	/* including hnotify */
++		cp = au_dfree.cache + i;
++		cp->cache = NULL;
++		init_llist_head(&cp->llist);
++	}
++	for (i = 0; i < AU_DFREE_Last; i++)
++		init_llist_head(au_dfree.llist + i);
++	INIT_DELAYED_WORK(&au_dfree.dwork, au_do_dfree);
++
 +	au_sbilist_init();
 +	sysaufs_brs_init();
 +	au_debug_init();
@@ -22036,6 +22147,7 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +out_sysaufs:
 +	sysaufs_fin();
 +	au_dy_fin();
++	flush_delayed_work(&au_dfree.dwork);
 +out:
 +	return err;
 +}
@@ -22051,14 +22163,15 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
 +	au_procfs_fin();
 +	sysaufs_fin();
 +	au_dy_fin();
++	flush_delayed_work(&au_dfree.dwork);
 +}
 +
 +module_init(aufs_init);
 +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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,89 @@
++++ linux/fs/aufs/module.h	2016-08-17 18:01:06.158556531 +0200
+@@ -0,0 +1,144 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -22086,6 +22199,7 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
 +#ifdef __KERNEL__
 +
 +#include <linux/slab.h>
++#include "debug.h"
 +
 +struct path;
 +struct seq_file;
@@ -22112,7 +22226,7 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
 +
 +/* ---------------------------------------------------------------------- */
 +
-+/* kmem cache */
++/* kmem cache and delayed free */
 +enum {
 +	AuCache_DINFO,
 +	AuCache_ICNTNR,
@@ -22123,19 +22237,54 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
 +	AuCache_Last
 +};
 +
++enum {
++	AU_DFREE_KFREE,
++	AU_DFREE_FREE_PAGE,
++	AU_DFREE_Last
++};
++
++struct au_cache {
++	struct kmem_cache	*cache;
++	struct llist_head	llist;	/* delayed free */
++};
++
++/*
++ * in order to reduce the cost of the internal timer, consolidate all the
++ * delayed free works into a single delayed_work.
++ */
++struct au_dfree {
++	struct au_cache		cache[AuCache_Last];
++	struct llist_head	llist[AU_DFREE_Last];
++	struct delayed_work	dwork;
++};
++
++extern struct au_dfree au_dfree;
++
 +#define AuCacheFlags		(SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
 +#define AuCache(type)		KMEM_CACHE(type, AuCacheFlags)
 +#define AuCacheCtor(type, ctor)	\
 +	kmem_cache_create(#type, sizeof(struct type), \
 +			  __alignof__(struct type), AuCacheFlags, ctor)
 +
-+extern struct kmem_cache *au_cachep[];
++#define AU_DFREE_DELAY		msecs_to_jiffies(10)
++#define AU_DFREE_BODY(lnode, llist) do {				\
++		if (llist_add(lnode, llist))				\
++			schedule_delayed_work(&au_dfree.dwork,		\
++					      AU_DFREE_DELAY);		\
++	} while (0)
++#define AU_CACHE_DFREE_FUNC(name, idx, lnode)				\
++	void au_cache_dfree_##name(struct au_##name *p)			\
++	{								\
++		struct au_cache *cp = au_dfree.cache + AuCache_##idx;	\
++		AU_DFREE_BODY(&p->lnode, &cp->llist);			\
++	}
 +
 +#define AuCacheFuncs(name, index) \
 +static inline struct au_##name *au_cache_alloc_##name(void) \
-+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
++{ return kmem_cache_alloc(au_dfree.cache[AuCache_##index].cache, GFP_NOFS); } \
 +static inline void au_cache_free_##name(struct au_##name *p) \
-+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
++{ kmem_cache_free(au_dfree.cache[AuCache_##index].cache, p); } \
++void au_cache_dfree_##name(struct au_##name *p)
 +
 +AuCacheFuncs(dinfo, DINFO);
 +AuCacheFuncs(icntnr, ICNTNR);
@@ -22146,11 +22295,30 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
 +AuCacheFuncs(hnotify, HNOTIFY);
 +#endif
 +
++static inline void au_delayed_kfree(const void *p)
++{
++	AuDebugOn(!p);
++	AuDebugOn(ksize(p) < sizeof(struct llist_node));
++
++	AU_DFREE_BODY((void *)p, au_dfree.llist + AU_DFREE_KFREE);
++}
++
++/* cast only */
++static inline void au_free_page(void *p)
++{
++	free_page((unsigned long)p);
++}
++
++static inline void au_delayed_free_page(unsigned long addr)
++{
++	AU_DFREE_BODY((void *)addr, au_dfree.llist + AU_DFREE_FREE_PAGE);
++}
++
 +#endif /* __KERNEL__ */
 +#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	2016-07-25 19:05:34.814493242 +0200
++++ linux/fs/aufs/mvdown.c	2016-08-17 18:01:06.158556531 +0200
 @@ -0,0 +1,704 @@
 +/*
 + * Copyright (C) 2011-2016 Junjiro R. Okajima
@@ -22851,15 +23019,15 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
 +	e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
 +	if (unlikely(e))
 +		err = -EFAULT;
-+	kfree(args);
++	au_delayed_kfree(args);
 +out:
 +	AuTraceErr(err);
 +	return err;
 +}
 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	2016-07-25 19:05:34.814493242 +0200
-@@ -0,0 +1,1859 @@
++++ linux/fs/aufs/opts.c	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,1860 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -24118,7 +24286,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +		}
 +	}
 +
-+	kfree(a);
++	au_delayed_kfree(a);
 +	dump_opts(opts);
 +	if (unlikely(err))
 +		au_opts_free(opts);
@@ -24540,7 +24708,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
 +		au_hn_inode_unlock(hdir);
 +
 +		if (!err && do_free) {
-+			kfree(wbr);
++			if (wbr)
++				au_delayed_kfree(wbr);
 +			br->br_wbr = NULL;
 +		}
 +	}
@@ -24936,8 +25105,8 @@ 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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,502 @@
++++ linux/fs/aufs/plink.c	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,514 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -24985,6 +25154,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +{
 +	int err;
 +	pid_t pid, ppid;
++	struct task_struct *parent, *prev;
 +	struct au_sbinfo *sbi;
 +
 +	SiMustAnyLock(sb);
@@ -24999,11 +25169,22 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
 +		goto out;
 +
 +	/* todo: it highly depends upon /sbin/mount.aufs */
++	prev = NULL;
++	parent = current;
++	ppid = 0;
 +	rcu_read_lock();
-+	ppid = task_pid_vnr(rcu_dereference(current->real_parent));
++	while (1) {
++		parent = rcu_dereference(parent->real_parent);
++		if (parent == prev)
++			break;
++		ppid = task_pid_vnr(parent);
++		if (pid == ppid) {
++			rcu_read_unlock();
++			goto out;
++		}
++		prev = parent;
++	}
 +	rcu_read_unlock();
-+	if (pid == ppid)
-+		goto out;
 +
 +	if (au_ftest_lock(flags, NOPLMW)) {
 +		/* if there is no i_mutex lock in VFS, we don't need to wait */
@@ -26360,8 +26541,8 @@ 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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,353 @@
++++ linux/fs/aufs/sbinfo.c	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,354 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -26397,7 +26578,7 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
 +	for (i = 0; i < AuPlink_NHASH; i++)
 +		AuDebugOn(!hlist_empty(&sbinfo->si_plink[i].head));
-+	au_nwt_fin(&sbinfo->si_nowait);
++	AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
 +
 +	AuDebugOn(percpu_counter_sum(&sbinfo->si_ninodes));
 +	percpu_counter_destroy(&sbinfo->si_ninodes);
@@ -26408,14 +26589,15 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +	au_br_free(sbinfo);
 +	au_rw_write_unlock(&sbinfo->si_rwsem);
 +
-+	kfree(sbinfo->si_branch);
++	au_delayed_kfree(sbinfo->si_branch);
 +	for (i = 0; i < AU_NPIDMAP; i++)
-+		kfree(sbinfo->au_si_pid.pid_bitmap[i]);
++		if (sbinfo->au_si_pid.pid_bitmap[i])
++			au_delayed_kfree(sbinfo->au_si_pid.pid_bitmap[i]);
 +	mutex_destroy(&sbinfo->au_si_pid.pid_mtx);
 +	mutex_destroy(&sbinfo->si_xib_mtx);
 +	AuRwDestroy(&sbinfo->si_rwsem);
 +
-+	kfree(sbinfo);
++	au_delayed_kfree(sbinfo);
 +}
 +
 +int au_si_alloc(struct super_block *sb)
@@ -26487,9 +26669,9 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
 +	return 0; /* success */
 +
 +out_br:
-+	kfree(sbinfo->si_branch);
++	au_delayed_kfree(sbinfo->si_branch);
 +out_sbinfo:
-+	kfree(sbinfo);
++	au_delayed_kfree(sbinfo);
 +out:
 +	return err;
 +}
@@ -26717,8 +26899,8 @@ 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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,111 @@
++++ linux/fs/aufs/spl.h	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,113 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -26745,6 +26927,7 @@ diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
 +
 +#ifdef __KERNEL__
 +
++#if 0
 +struct au_splhead {
 +	spinlock_t		spin;
 +	struct list_head	head;
@@ -26777,6 +26960,7 @@ diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
 +	list_del_rcu(list);
 +	spin_unlock(&spl->spin);
 +}
++#endif
 +
 +/* ---------------------------------------------------------------------- */
 +
@@ -26832,8 +27016,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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,1039 @@
++++ linux/fs/aufs/super.c	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,1038 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -26882,8 +27066,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +{
 +	struct inode *inode = container_of(head, struct inode, i_rcu);
 +
-+	INIT_HLIST_HEAD(&inode->i_dentry);
-+	au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
++	au_cache_dfree_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
 +}
 +
 +static void aufs_destroy_inode(struct inode *inode)
@@ -27665,7 +27848,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +out_mtx:
 +	inode_unlock(inode);
 +out_opts:
-+	free_page((unsigned long)opts.opt);
++	au_delayed_free_page((unsigned long)opts.opt);
 +out:
 +	err = cvt_err(err);
 +	AuTraceErr(err);
@@ -27806,7 +27989,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
 +	kobject_put(&sbinfo->si_kobj);
 +	sb->s_fs_info = NULL;
 +out_opts:
-+	free_page((unsigned long)opts.opt);
++	au_delayed_free_page((unsigned long)opts.opt);
 +out:
 +	AuTraceErr(err);
 +	err = cvt_err(err);
@@ -28730,7 +28913,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	2016-07-25 19:05:34.817826663 +0200
++++ linux/fs/aufs/sysfs.c	2016-08-17 18:01:06.161889951 +0200
 @@ -0,0 +1,376 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -28943,7 +29126,7 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
 +		if (unlikely(err == PAGE_SIZE))
 +			err = -EFBIG;
 +	}
-+	kfree(seq);
++	au_delayed_kfree(seq);
 +out_unlock:
 +	si_read_unlock(sb);
 +out:
@@ -29014,9 +29197,9 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
 +		err = -EFAULT;
 +
 +out_seq:
-+	kfree(seq);
++	au_delayed_kfree(seq);
 +out_buf:
-+	free_page((unsigned long)buf);
++	au_delayed_free_page((unsigned long)buf);
 +out:
 +	si_read_unlock(sb);
 +	return err;
@@ -29271,8 +29454,8 @@ 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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,889 @@
++++ linux/fs/aufs/vdir.c	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,899 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -29385,7 +29568,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +	struct hlist_node *node;
 +
 +	hlist_for_each_entry_safe(pos, node, head, wh_hash)
-+		kfree(pos);
++		au_delayed_kfree(pos);
 +}
 +
 +static void au_nhash_de_do_free(struct hlist_head *head)
@@ -29394,7 +29577,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +	struct hlist_node *node;
 +
 +	hlist_for_each_entry_safe(pos, node, head, hash)
-+		au_cache_free_vdir_dehstr(pos);
++		au_cache_dfree_vdir_dehstr(pos);
 +}
 +
 +static void au_nhash_do_free(struct au_nhash *nhash,
@@ -29412,7 +29595,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +		nhash_count(head);
 +		free(head++);
 +	}
-+	kfree(nhash->nh_head);
++	au_delayed_kfree(nhash->nh_head);
 +}
 +
 +void au_nhash_wh_free(struct au_nhash *whlist)
@@ -29455,6 +29638,8 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +	AuDebugOn(!nhash->nh_num || !nhash->nh_head);
 +
 +	v = 0;
++	if (len > 8)
++		len = 8;
 +	while (len--)
 +		v += *name++;
 +	/* v = hash_long(v, magic_bit); */
@@ -29623,15 +29808,23 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +
 +/* ---------------------------------------------------------------------- */
 +
-+void au_vdir_free(struct au_vdir *vdir)
++void au_vdir_free(struct au_vdir *vdir, int atonce)
 +{
 +	unsigned char **deblk;
 +
 +	deblk = vdir->vd_deblk;
-+	while (vdir->vd_nblk--)
-+		kfree(*deblk++);
-+	kfree(vdir->vd_deblk);
-+	au_cache_free_vdir(vdir);
++	if (!atonce) {
++		while (vdir->vd_nblk--)
++			au_delayed_kfree(*deblk++);
++		au_delayed_kfree(vdir->vd_deblk);
++		au_cache_dfree_vdir(vdir);
++	} else {
++		/* not delayed */
++		while (vdir->vd_nblk--)
++			kfree(*deblk++);
++		kfree(vdir->vd_deblk);
++		au_cache_free_vdir(vdir);
++	}
 +}
 +
 +static struct au_vdir *alloc_vdir(struct file *file)
@@ -29665,10 +29858,10 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +	if (!err)
 +		return vdir; /* success */
 +
-+	kfree(vdir->vd_deblk);
++	au_delayed_kfree(vdir->vd_deblk);
 +
 +out_free:
-+	au_cache_free_vdir(vdir);
++	au_cache_dfree_vdir(vdir);
 +out:
 +	vdir = ERR_PTR(err);
 +	return vdir;
@@ -29680,7 +29873,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +	union au_vdir_deblk_p p, deblk_end;
 +
 +	while (vdir->vd_nblk > 1) {
-+		kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
++		au_delayed_kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
 +		/* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
 +		vdir->vd_nblk--;
 +	}
@@ -29811,7 +30004,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +		}
 +	}
 +
-+	free_page((unsigned long)o);
++	au_delayed_free_page((unsigned long)o);
 +
 +out:
 +	AuTraceErr(err);
@@ -29950,7 +30143,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +		if (allocated)
 +			au_set_ivdir(inode, allocated);
 +	} else if (allocated)
-+		au_vdir_free(allocated);
++		au_vdir_free(allocated, /*atonce*/0);
 +
 +out:
 +	return err;
@@ -30044,7 +30237,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
 +		if (allocated)
 +			au_set_fvdir_cache(file, allocated);
 +	} else if (allocated)
-+		au_vdir_free(allocated);
++		au_vdir_free(allocated, /*atonce*/0);
 +
 +out:
 +	return err;
@@ -31052,8 +31245,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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,310 @@
++++ linux/fs/aufs/vfsub.h	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,316 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -31252,6 +31445,12 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
 +	return flags;
 +}
 +
++static inline int vfsub_file_execed(struct file *file)
++{
++	/* todo: direct access f_flags */
++	return !!(vfsub_file_flags(file) & __FMODE_EXEC);
++}
++
 +#if 0 /* reserved */
 +static inline void vfsub_file_accessed(struct file *h_file)
 +{
@@ -31366,7 +31565,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
 +#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	2016-07-25 19:05:34.817826663 +0200
++++ linux/fs/aufs/wbr_policy.c	2016-08-17 18:01:06.161889951 +0200
 @@ -0,0 +1,765 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -31831,7 +32030,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
 +
 +	mfs->mfsrr_bytes = bavail;
 +	AuDbg("b%d\n", mfs->mfs_bindex);
-+	kfree(st);
++	au_delayed_kfree(st);
 +}
 +
 +static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
@@ -32135,7 +32334,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	2016-07-25 19:05:34.817826663 +0200
++++ linux/fs/aufs/whout.c	2016-08-17 18:01:06.161889951 +0200
 @@ -0,0 +1,1060 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -32301,7 +32500,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +
 +out_name:
 +	if (name != defname)
-+		kfree(name);
++		au_delayed_kfree(name);
 +out:
 +	AuTraceErrPtr(dentry);
 +	return dentry;
@@ -32740,7 +32939,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +	au_br_put(a->br);
 +	si_write_unlock(a->sb);
 +	au_nwt_done(&au_sbi(a->sb)->si_nowait);
-+	kfree(arg);
++	au_delayed_kfree(arg);
 +	if (unlikely(err))
 +		AuIOErr("err %d\n", err);
 +}
@@ -32768,7 +32967,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +		if (unlikely(wkq_err)) {
 +			atomic_dec(&br->br_wbr->wbr_wh_running);
 +			au_br_put(br);
-+			kfree(arg);
++			au_delayed_kfree(arg);
 +		}
 +		do_dec = 0;
 +	}
@@ -32927,7 +33126,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +	wh_dentry = ERR_PTR(err);
 +	if (!err) {
 +		wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
-+		kfree(wh_name.name);
++		au_delayed_kfree(wh_name.name);
 +	}
 +	return wh_dentry;
 +}
@@ -33003,7 +33202,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +			break;
 +		}
 +	}
-+	free_page((unsigned long)wh_name.name);
++	au_delayed_free_page((unsigned long)wh_name.name);
 +
 +out:
 +	return err;
@@ -33045,7 +33244,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +		rdhash = AUFS_RDHASH_DEF;
 +	err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
 +	if (unlikely(err)) {
-+		kfree(whtmp);
++		au_delayed_kfree(whtmp);
 +		whtmp = ERR_PTR(err);
 +	}
 +
@@ -33060,7 +33259,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
 +	dput(whtmp->wh_dentry);
 +	iput(whtmp->dir);
 +	au_nhash_wh_free(&whtmp->whlist);
-+	kfree(whtmp);
++	au_delayed_kfree(whtmp);
 +}
 +
 +/*
@@ -33288,8 +33487,8 @@ 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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,218 @@
++++ linux/fs/aufs/wkq.c	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,213 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -33346,7 +33545,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
 +	else {
 +		kobject_put(wkinfo->kobj);
 +		module_put(THIS_MODULE); /* todo: ?? */
-+		kfree(wkinfo);
++		au_delayed_kfree(wkinfo);
 +	}
 +}
 +
@@ -33369,7 +33568,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
 +
 +static void au_wkq_comp_free(struct completion *comp)
 +{
-+	kfree(comp);
++	au_delayed_kfree(comp);
 +}
 +
 +#else
@@ -33450,7 +33649,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
 +	int err;
 +	struct au_wkinfo *wkinfo;
 +
-+	percpu_counter_inc(&au_sbi(sb)->si_nowait.nw_len);
++	atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
 +
 +	/*
 +	 * wkq_func() must free this wkinfo.
@@ -33480,16 +33679,11 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
 +
 +void au_nwt_init(struct au_nowait_tasks *nwt)
 +{
-+	percpu_counter_init(&nwt->nw_len, 0, GFP_NOFS);
++	atomic_set(&nwt->nw_len, 0);
++	/* smp_mb(); */ /* atomic_set */
 +	init_waitqueue_head(&nwt->nw_wq);
 +}
 +
-+void au_nwt_fin(struct au_nowait_tasks *nwt)
-+{
-+	AuDebugOn(percpu_counter_sum(&nwt->nw_len));
-+	percpu_counter_destroy(&nwt->nw_len);
-+}
-+
 +void au_wkq_fin(void)
 +{
 +	destroy_workqueue(au_wkq);
@@ -33510,8 +33704,8 @@ 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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,95 @@
++++ linux/fs/aufs/wkq.h	2016-08-17 18:01:06.161889951 +0200
+@@ -0,0 +1,93 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -33549,7 +33743,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
 + * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
 + */
 +struct au_nowait_tasks {
-+	struct percpu_counter	nw_len;
++	atomic_t		nw_len;
 +	wait_queue_head_t	nw_wq;
 +};
 +
@@ -33576,7 +33770,6 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
 +int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
 +		  unsigned int flags);
 +void au_nwt_init(struct au_nowait_tasks *nwt);
-+void au_nwt_fin(struct au_nowait_tasks *nwt);
 +int __init au_wkq_init(void);
 +void au_wkq_fin(void);
 +
@@ -33594,14 +33787,13 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
 +
 +static inline void au_nwt_done(struct au_nowait_tasks *nwt)
 +{
-+	percpu_counter_dec(&nwt->nw_len);
-+	if (!percpu_counter_sum(&nwt->nw_len))
++	if (atomic_dec_and_test(&nwt->nw_len))
 +		wake_up_all(&nwt->nw_wq);
 +}
 +
 +static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
 +{
-+	wait_event(nwt->nw_wq, !percpu_counter_sum(&nwt->nw_len));
++	wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
 +	return 0;
 +}
 +
@@ -33609,8 +33801,8 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
 +#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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,345 @@
++++ linux/fs/aufs/xattr.c	2016-08-17 18:01:06.165223371 +0200
+@@ -0,0 +1,347 @@
 +/*
 + * Copyright (C) 2014-2016 Junjiro R. Okajima
 + *
@@ -33789,10 +33981,12 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
 +		AuTraceErr(err);
 +	}
 +
-+	kfree(value);
++	if (value)
++		au_delayed_kfree(value);
 +
 +out_free:
-+	kfree(o);
++	if (o)
++		au_delayed_kfree(o);
 +out:
 +	if (!unlocked)
 +		inode_unlock(h_isrc);
@@ -33958,8 +34152,8 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
 +#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	2016-07-25 19:05:34.817826663 +0200
-@@ -0,0 +1,1317 @@
++++ linux/fs/aufs/xino.c	2016-08-17 18:01:06.165223371 +0200
+@@ -0,0 +1,1318 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
 + *
@@ -34300,7 +34494,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +		AuErr1("statfs err %d, ignored\n", err);
 +
 +out_st:
-+	kfree(st);
++	au_delayed_kfree(st);
 +out:
 +	return err;
 +}
@@ -34335,7 +34529,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +	au_br_put(br);
 +	si_write_unlock(sb);
 +	au_nwt_done(&au_sbi(sb)->si_nowait);
-+	kfree(args);
++	au_delayed_kfree(args);
 +}
 +
 +static int xino_trunc_test(struct super_block *sb, struct au_branch *br)
@@ -34377,7 +34571,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +	args = kmalloc(sizeof(*args), GFP_NOFS);
 +	if (unlikely(!args)) {
 +		AuErr1("no memory\n");
-+		goto out_args;
++		goto out;
 +	}
 +
 +	au_br_get(br);
@@ -34389,9 +34583,8 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +
 +	pr_err("wkq %d\n", wkq_err);
 +	au_br_put(br);
++	au_delayed_kfree(args);
 +
-+out_args:
-+	kfree(args);
 +out:
 +	atomic_dec(&br->br_xino_running);
 +}
@@ -34914,7 +35107,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +				(sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
 +		else
 +			AuDbg("b%d\n", bindex);
-+	free_page((unsigned long)page);
++	au_delayed_free_page((unsigned long)page);
 +
 +out:
 +	return err;
@@ -34991,7 +35184,8 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +	if (sbinfo->si_xib)
 +		fput(sbinfo->si_xib);
 +	sbinfo->si_xib = NULL;
-+	free_page((unsigned long)sbinfo->si_xib_buf);
++	if (sbinfo->si_xib_buf)
++		au_delayed_free_page((unsigned long)sbinfo->si_xib_buf);
 +	sbinfo->si_xib_buf = NULL;
 +}
 +
@@ -35034,7 +35228,8 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +	goto out; /* success */
 +
 +out_free:
-+	free_page((unsigned long)sbinfo->si_xib_buf);
++	if (sbinfo->si_xib_buf)
++		au_delayed_free_page((unsigned long)sbinfo->si_xib_buf);
 +	sbinfo->si_xib_buf = NULL;
 +	if (err >= 0)
 +		err = -EIO;
@@ -35127,7 +35322,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +			fput(p->new);
 +		else
 +			break;
-+	kfree(fpair);
++	au_delayed_kfree(fpair);
 +out:
 +	return err;
 +}
@@ -35238,7 +35433,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
 +			if (!IS_ERR(file))
 +				au_xino_brid_set(sb, br->br_id);
 +		}
-+		free_page((unsigned long)page);
++		au_delayed_free_page((unsigned long)page);
 +	} else {
 +		file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
 +		if (IS_ERR(file))
@@ -35279,7 +35474,7 @@ 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	2016-07-25 19:05:34.817826663 +0200
++++ linux/include/uapi/linux/aufs_type.h	2016-08-17 18:01:21.295617591 +0200
 @@ -0,0 +1,419 @@
 +/*
 + * Copyright (C) 2005-2016 Junjiro R. Okajima
@@ -35322,7 +35517,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin
 +
 +#include <linux/limits.h>
 +
-+#define AUFS_VERSION	"4.x-rcN-20160704"
++#define AUFS_VERSION	"4.7-20160815"
 +
 +/* todo? move this to linux-2.6.19/include/magic.h */
 +#define AUFS_SUPER_MAGIC	('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -35700,7 +35895,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin
 +#define AUFS_CTL_FHSM_FD	_IOW(AuCtlType, AuCtl_FHSM_FD, int)
 +
 +#endif /* __AUFS_TYPE_H__ */
-aufs4.x-rcN loopback patch
+aufs4.7 loopback patch
 
 diff --git a/drivers/block/loop.c b/drivers/block/loop.c
 index 7339e65..76e5da4 100644
@@ -35882,10 +36077,10 @@ index fb2237c..c3888c5 100644
  	unsigned	lo_blocksize;
  	void		*key_data; 
 diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
-index 504b767..09426ad 100644
+index 00475fb..01390e1 100644
 --- a/fs/aufs/f_op.c
 +++ b/fs/aufs/f_op.c
-@@ -346,7 +346,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
+@@ -348,7 +348,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
  	if (IS_ERR(h_file))
  		goto out;
  
@@ -35895,12 +36090,12 @@ index 504b767..09426ad 100644
  		if (file->f_mapping != h_file->f_mapping) {
  			file->f_mapping = h_file->f_mapping;
 diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
-index 5711e7a..9df5d16 100644
+index e92a345..35f4d48 100644
 --- a/fs/aufs/loop.c
 +++ b/fs/aufs/loop.c
 @@ -131,3 +131,19 @@ void au_loopback_fin(void)
  		symbol_put(loop_backing_file);
- 	kfree(au_warn_loopback_array);
+ 	au_delayed_kfree(au_warn_loopback_array);
  }
 +
 +/* ---------------------------------------------------------------------- */
@@ -35944,10 +36139,10 @@ index 48bf070..66afec7 100644
  
  #endif /* __KERNEL__ */
 diff --git a/fs/aufs/super.c b/fs/aufs/super.c
-index 8bd2d9c..26581c0 100644
+index 58a773c..75f212c 100644
 --- a/fs/aufs/super.c
 +++ b/fs/aufs/super.c
-@@ -832,7 +832,10 @@ static const struct super_operations aufs_sop = {
+@@ -831,7 +831,10 @@ static const struct super_operations aufs_sop = {
  	.statfs		= aufs_statfs,
  	.put_super	= aufs_put_super,
  	.sync_fs	= aufs_sync_fs,
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/kernel.git/commitdiff/f0c0a0075ebbd8e5d2b07223d3e6a049d302da27



More information about the pld-cvs-commit mailing list