aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in1
-rw-r--r--cmd/Makefile.in1
-rw-r--r--cmd/mount_zfs/Makefile.in1
-rw-r--r--cmd/sas_switch_id/Makefile.in1
-rw-r--r--cmd/zdb/Makefile.in1
-rw-r--r--cmd/zfs/Makefile.in1
-rw-r--r--cmd/zinject/Makefile.in1
-rw-r--r--cmd/zpios/Makefile.in1
-rw-r--r--cmd/zpool/Makefile.in1
-rw-r--r--cmd/zpool_id/Makefile.in1
-rw-r--r--cmd/zpool_layout/Makefile.in1
-rw-r--r--cmd/ztest/Makefile.in1
-rw-r--r--cmd/zvol_id/Makefile.in1
-rw-r--r--config/kernel-shrink.m464
-rw-r--r--config/kernel.m43
-rwxr-xr-xconfigure420
-rw-r--r--dracut/90zfs/Makefile.in1
-rw-r--r--dracut/Makefile.in1
-rw-r--r--etc/Makefile.in1
-rw-r--r--etc/init.d/Makefile.in1
-rw-r--r--etc/zfs/Makefile.in1
-rw-r--r--include/Makefile.in1
-rw-r--r--include/linux/Makefile.in1
-rw-r--r--include/sys/Makefile.in1
-rw-r--r--include/sys/arc.h15
-rw-r--r--include/sys/fm/Makefile.in1
-rw-r--r--include/sys/fm/fs/Makefile.in1
-rw-r--r--include/sys/fs/Makefile.in1
-rw-r--r--include/sys/zfs_vfsops.h5
-rw-r--r--include/sys/zpl.h2
-rw-r--r--lib/Makefile.in1
-rw-r--r--lib/libavl/Makefile.in1
-rw-r--r--lib/libefi/Makefile.in1
-rw-r--r--lib/libnvpair/Makefile.in1
-rw-r--r--lib/libshare/Makefile.in1
-rw-r--r--lib/libspl/Makefile.in1
-rw-r--r--lib/libspl/asm-generic/Makefile.in1
-rw-r--r--lib/libspl/asm-i386/Makefile.in1
-rw-r--r--lib/libspl/asm-x86_64/Makefile.in1
-rw-r--r--lib/libspl/include/Makefile.in1
-rw-r--r--lib/libspl/include/ia32/Makefile.in1
-rw-r--r--lib/libspl/include/ia32/sys/Makefile.in1
-rw-r--r--lib/libspl/include/rpc/Makefile.in1
-rw-r--r--lib/libspl/include/sys/Makefile.in1
-rw-r--r--lib/libspl/include/sys/dktp/Makefile.in1
-rw-r--r--lib/libspl/include/sys/sysevent/Makefile.in1
-rw-r--r--lib/libspl/include/util/Makefile.in1
-rw-r--r--lib/libunicode/Makefile.in1
-rw-r--r--lib/libuutil/Makefile.in1
-rw-r--r--lib/libzfs/Makefile.in1
-rw-r--r--lib/libzpool/Makefile.in1
-rw-r--r--man/Makefile.in1
-rw-r--r--man/man8/Makefile.in1
-rw-r--r--module/zfs/arc.c188
-rw-r--r--module/zfs/zfs_vfsops.c21
-rw-r--r--module/zfs/zfs_znode.c2
-rw-r--r--module/zfs/zpl_super.c126
-rw-r--r--scripts/Makefile.in1
-rw-r--r--scripts/zpios-profile/Makefile.in1
-rw-r--r--scripts/zpios-test/Makefile.in1
-rw-r--r--scripts/zpool-config/Makefile.in1
-rw-r--r--scripts/zpool-layout/Makefile.in1
-rw-r--r--udev/Makefile.in1
-rw-r--r--udev/rules.d/Makefile.in1
-rw-r--r--zfs_config.h.in9
65 files changed, 858 insertions, 51 deletions
diff --git a/Makefile.in b/Makefile.in
index 332efc173..37c813cd3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -92,6 +92,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/Makefile.in b/cmd/Makefile.in
index ee3f4bef2..eb86e2796 100644
--- a/cmd/Makefile.in
+++ b/cmd/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/mount_zfs/Makefile.in b/cmd/mount_zfs/Makefile.in
index 73660d21b..44d07667e 100644
--- a/cmd/mount_zfs/Makefile.in
+++ b/cmd/mount_zfs/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/sas_switch_id/Makefile.in b/cmd/sas_switch_id/Makefile.in
index fb6ea65ec..889da1785 100644
--- a/cmd/sas_switch_id/Makefile.in
+++ b/cmd/sas_switch_id/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zdb/Makefile.in b/cmd/zdb/Makefile.in
index da3119592..4fd55e5fa 100644
--- a/cmd/zdb/Makefile.in
+++ b/cmd/zdb/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zfs/Makefile.in b/cmd/zfs/Makefile.in
index 55ca80892..0b9b4dcc6 100644
--- a/cmd/zfs/Makefile.in
+++ b/cmd/zfs/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zinject/Makefile.in b/cmd/zinject/Makefile.in
index 5e6f90ecb..8adfaab39 100644
--- a/cmd/zinject/Makefile.in
+++ b/cmd/zinject/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zpios/Makefile.in b/cmd/zpios/Makefile.in
index cf672f1e1..c0a84df6b 100644
--- a/cmd/zpios/Makefile.in
+++ b/cmd/zpios/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zpool/Makefile.in b/cmd/zpool/Makefile.in
index b915006f4..127b93690 100644
--- a/cmd/zpool/Makefile.in
+++ b/cmd/zpool/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zpool_id/Makefile.in b/cmd/zpool_id/Makefile.in
index aadd12413..29f83a3ff 100644
--- a/cmd/zpool_id/Makefile.in
+++ b/cmd/zpool_id/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zpool_layout/Makefile.in b/cmd/zpool_layout/Makefile.in
index e1b164313..514e88f5f 100644
--- a/cmd/zpool_layout/Makefile.in
+++ b/cmd/zpool_layout/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/ztest/Makefile.in b/cmd/ztest/Makefile.in
index e99cc9e85..dc6549b6c 100644
--- a/cmd/ztest/Makefile.in
+++ b/cmd/ztest/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/cmd/zvol_id/Makefile.in b/cmd/zvol_id/Makefile.in
index d6719fdb6..d657c8007 100644
--- a/cmd/zvol_id/Makefile.in
+++ b/cmd/zvol_id/Makefile.in
@@ -72,6 +72,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/config/kernel-shrink.m4 b/config/kernel-shrink.m4
new file mode 100644
index 000000000..ea748c974
--- /dev/null
+++ b/config/kernel-shrink.m4
@@ -0,0 +1,64 @@
+dnl #
+dnl # 3.1 API change
+dnl # The super_block structure now stores a per-filesystem shrinker.
+dnl # This interface is preferable because it can be used to specifically
+dnl # target only the zfs filesystem for pruning.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SHRINK], [
+ AC_MSG_CHECKING([whether super_block has s_shrink])
+ ZFS_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+ ],[
+ int (*shrink)(struct shrinker *, struct shrink_control *sc)
+ __attribute__ ((unused)) = NULL;
+ struct super_block sb __attribute__ ((unused)) = {
+ .s_shrink.shrink = shrink,
+ .s_shrink.seeks = DEFAULT_SEEKS,
+ .s_shrink.batch = 0,
+ };
+ ],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SHRINK, 1, [struct super_block has s_shrink])
+
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_NR_CACHED_OBJECTS], [
+ AC_MSG_CHECKING([whether sops->nr_cached_objects() exists])
+ ZFS_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+ ],[
+ int (*nr_cached_objects)(struct super_block *)
+ __attribute__ ((unused)) = NULL;
+ struct super_operations sops __attribute__ ((unused)) = {
+ .nr_cached_objects = nr_cached_objects,
+ };
+ ],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_NR_CACHED_OBJECTS, 1,
+ [sops->nr_cached_objects() exists])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
+ AC_MSG_CHECKING([whether sops->free_cached_objects() exists])
+ ZFS_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+ ],[
+ void (*free_cached_objects)(struct super_block *, int)
+ __attribute__ ((unused)) = NULL;
+ struct super_operations sops __attribute__ ((unused)) = {
+ .free_cached_objects = free_cached_objects,
+ };
+ ],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FREE_CACHED_OBJECTS, 1,
+ [sops->free_cached_objects() exists])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/config/kernel.m4 b/config/kernel.m4
index 63a3237ec..2afe77e63 100644
--- a/config/kernel.m4
+++ b/config/kernel.m4
@@ -34,12 +34,15 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_XATTR_HANDLER_SET
ZFS_AC_KERNEL_FSYNC
ZFS_AC_KERNEL_EVICT_INODE
+ ZFS_AC_KERNEL_NR_CACHED_OBJECTS
+ ZFS_AC_KERNEL_FREE_CACHED_OBJECTS
ZFS_AC_KERNEL_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_D_OBTAIN_ALIAS
ZFS_AC_KERNEL_CHECK_DISK_SIZE_CHANGE
ZFS_AC_KERNEL_TRUNCATE_SETSIZE
ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY
ZFS_AC_KERNEL_MOUNT_NODEV
+ ZFS_AC_KERNEL_SHRINK
ZFS_AC_KERNEL_BDI
ZFS_AC_KERNEL_BDI_SETUP_AND_REGISTER
ZFS_AC_KERNEL_SET_NLINK
diff --git a/configure b/configure
index d6f405bbb..f30b1ffcb 100755
--- a/configure
+++ b/configure
@@ -14774,6 +14774,144 @@ fi
+ { $as_echo "$as_me:$LINENO: checking whether sops->nr_cached_objects() exists" >&5
+$as_echo_n "checking whether sops->nr_cached_objects() exists... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+ #include <linux/fs.h>
+
+int
+main (void)
+{
+
+ int (*nr_cached_objects)(struct super_block *)
+ __attribute__ ((unused)) = NULL;
+ struct super_operations sops __attribute__ ((unused)) = {
+ .nr_cached_objects = nr_cached_objects,
+ };
+
+ ;
+ return 0;
+}
+
+_ACEOF
+
+
+ rm -Rf build && mkdir -p build
+ echo "obj-m := conftest.o" >build/Makefile
+ if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NR_CACHED_OBJECTS 1
+_ACEOF
+
+
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+ rm -Rf build
+
+
+
+
+ { $as_echo "$as_me:$LINENO: checking whether sops->free_cached_objects() exists" >&5
+$as_echo_n "checking whether sops->free_cached_objects() exists... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+ #include <linux/fs.h>
+
+int
+main (void)
+{
+
+ void (*free_cached_objects)(struct super_block *, int)
+ __attribute__ ((unused)) = NULL;
+ struct super_operations sops __attribute__ ((unused)) = {
+ .free_cached_objects = free_cached_objects,
+ };
+
+ ;
+ return 0;
+}
+
+_ACEOF
+
+
+ rm -Rf build && mkdir -p build
+ echo "obj-m := conftest.o" >build/Makefile
+ if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FREE_CACHED_OBJECTS 1
+_ACEOF
+
+
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+ rm -Rf build
+
+
+
+
{ $as_echo "$as_me:$LINENO: checking whether symbol insert_inode_locked is exported" >&5
$as_echo_n "checking whether symbol insert_inode_locked is exported... " >&6; }
grep -q -E '[[:space:]]insert_inode_locked[[:space:]]' \
@@ -15107,6 +15245,78 @@ fi
+ { $as_echo "$as_me:$LINENO: checking whether super_block has s_shrink" >&5
+$as_echo_n "checking whether super_block has s_shrink... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+ #include <linux/fs.h>
+
+int
+main (void)
+{
+
+ int (*shrink)(struct shrinker *, struct shrink_control *sc)
+ __attribute__ ((unused)) = NULL;
+ struct super_block sb __attribute__ ((unused)) = {
+ .s_shrink.shrink = shrink,
+ .s_shrink.seeks = DEFAULT_SEEKS,
+ .s_shrink.batch = 0,
+ };
+
+ ;
+ return 0;
+}
+
+_ACEOF
+
+
+ rm -Rf build && mkdir -p build
+ echo "obj-m := conftest.o" >build/Makefile
+ if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK 1
+_ACEOF
+
+
+
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+ rm -Rf build
+
+
+
+
{ $as_echo "$as_me:$LINENO: checking whether super_block has s_bdi" >&5
$as_echo_n "checking whether super_block has s_bdi... " >&6; }
@@ -19611,6 +19821,144 @@ fi
+ { $as_echo "$as_me:$LINENO: checking whether sops->nr_cached_objects() exists" >&5
+$as_echo_n "checking whether sops->nr_cached_objects() exists... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+ #include <linux/fs.h>
+
+int
+main (void)
+{
+
+ int (*nr_cached_objects)(struct super_block *)
+ __attribute__ ((unused)) = NULL;
+ struct super_operations sops __attribute__ ((unused)) = {
+ .nr_cached_objects = nr_cached_objects,
+ };
+
+ ;
+ return 0;
+}
+
+_ACEOF
+
+
+ rm -Rf build && mkdir -p build
+ echo "obj-m := conftest.o" >build/Makefile
+ if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_NR_CACHED_OBJECTS 1
+_ACEOF
+
+
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+ rm -Rf build
+
+
+
+
+ { $as_echo "$as_me:$LINENO: checking whether sops->free_cached_objects() exists" >&5
+$as_echo_n "checking whether sops->free_cached_objects() exists... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+ #include <linux/fs.h>
+
+int
+main (void)
+{
+
+ void (*free_cached_objects)(struct super_block *, int)
+ __attribute__ ((unused)) = NULL;
+ struct super_operations sops __attribute__ ((unused)) = {
+ .free_cached_objects = free_cached_objects,
+ };
+
+ ;
+ return 0;
+}
+
+_ACEOF
+
+
+ rm -Rf build && mkdir -p build
+ echo "obj-m := conftest.o" >build/Makefile
+ if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FREE_CACHED_OBJECTS 1
+_ACEOF
+
+
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+ rm -Rf build
+
+
+
+
{ $as_echo "$as_me:$LINENO: checking whether symbol insert_inode_locked is exported" >&5
$as_echo_n "checking whether symbol insert_inode_locked is exported... " >&6; }
grep -q -E '[[:space:]]insert_inode_locked[[:space:]]' \
@@ -19944,6 +20292,78 @@ fi
+ { $as_echo "$as_me:$LINENO: checking whether super_block has s_shrink" >&5
+$as_echo_n "checking whether super_block has s_shrink... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+ #include <linux/fs.h>
+
+int
+main (void)
+{
+
+ int (*shrink)(struct shrinker *, struct shrink_control *sc)
+ __attribute__ ((unused)) = NULL;
+ struct super_block sb __attribute__ ((unused)) = {
+ .s_shrink.shrink = shrink,
+ .s_shrink.seeks = DEFAULT_SEEKS,
+ .s_shrink.batch = 0,
+ };
+
+ ;
+ return 0;
+}
+
+_ACEOF
+
+
+ rm -Rf build && mkdir -p build
+ echo "obj-m := conftest.o" >build/Makefile
+ if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+ { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SHRINK 1
+_ACEOF
+
+
+
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+ rm -Rf build
+
+
+
+
{ $as_echo "$as_me:$LINENO: checking whether super_block has s_bdi" >&5
$as_echo_n "checking whether super_block has s_bdi... " >&6; }
diff --git a/dracut/90zfs/Makefile.in b/dracut/90zfs/Makefile.in
index cc7961812..ca1d86063 100644
--- a/dracut/90zfs/Makefile.in
+++ b/dracut/90zfs/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/dracut/Makefile.in b/dracut/Makefile.in
index 1c6b3e609..f385985d2 100644
--- a/dracut/Makefile.in
+++ b/dracut/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/etc/Makefile.in b/etc/Makefile.in
index a2e398604..481d0cdd6 100644
--- a/etc/Makefile.in
+++ b/etc/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/etc/init.d/Makefile.in b/etc/init.d/Makefile.in
index 9eb8ae7b4..f4d085485 100644
--- a/etc/init.d/Makefile.in
+++ b/etc/init.d/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/etc/zfs/Makefile.in b/etc/zfs/Makefile.in
index 6c81f5d8c..b421d59bc 100644
--- a/etc/zfs/Makefile.in
+++ b/etc/zfs/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/include/Makefile.in b/include/Makefile.in
index f82fdb267..18e235722 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/include/linux/Makefile.in b/include/linux/Makefile.in
index e50b89b9b..030437b44 100644
--- a/include/linux/Makefile.in
+++ b/include/linux/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/include/sys/Makefile.in b/include/sys/Makefile.in
index b17649b02..012ffe9f7 100644
--- a/include/sys/Makefile.in
+++ b/include/sys/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/include/sys/arc.h b/include/sys/arc.h
index 8f189c62d..dd9b128bc 100644
--- a/include/sys/arc.h
+++ b/include/sys/arc.h
@@ -34,16 +34,27 @@ extern "C" {
#include <sys/zio.h>
#include <sys/dmu.h>
#include <sys/spa.h>
+#include <sys/refcount.h>
typedef struct arc_buf_hdr arc_buf_hdr_t;
typedef struct arc_buf arc_buf_t;
+typedef struct arc_prune arc_prune_t;
typedef void arc_done_func_t(zio_t *zio, arc_buf_t *buf, void *private);
+typedef void arc_prune_func_t(int64_t bytes, void *private);
typedef int arc_evict_func_t(void *private);
/* generic arc_done_func_t's which you can use */
arc_done_func_t arc_bcopy_func;
arc_done_func_t arc_getbuf_func;
+/* generic arc_prune_func_t wrapper for callbacks */
+struct arc_prune {
+ arc_prune_func_t *p_pfunc;
+ void *p_private;
+ list_node_t p_node;
+ refcount_t p_refcnt;
+};
+
struct arc_buf {
arc_buf_hdr_t *b_hdr;
arc_buf_t *b_next;
@@ -113,9 +124,13 @@ zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
arc_done_func_t *ready, arc_done_func_t *done, void *private,
int priority, int zio_flags, const zbookmark_t *zb);
+arc_prune_t *arc_add_prune_callback(arc_prune_func_t *func, void *private);
+void arc_remove_prune_callback(arc_prune_t *p);
+
void arc_set_callback(arc_buf_t *buf, arc_evict_func_t *func, void *private);
int arc_buf_evict(arc_buf_t *buf);
+void arc_adjust_meta(int64_t adjustment, boolean_t may_prune);
void arc_flush(spa_t *spa);
void arc_tempreserve_clear(uint64_t reserve);
int arc_tempreserve_space(uint64_t reserve, uint64_t txg);
diff --git a/include/sys/fm/Makefile.in b/include/sys/fm/Makefile.in
index e3fd84cfd..932e5e732 100644
--- a/include/sys/fm/Makefile.in
+++ b/include/sys/fm/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/include/sys/fm/fs/Makefile.in b/include/sys/fm/fs/Makefile.in
index 40952616b..bbcb1c258 100644
--- a/include/sys/fm/fs/Makefile.in
+++ b/include/sys/fm/fs/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/include/sys/fs/Makefile.in b/include/sys/fs/Makefile.in
index db73ab862..da86a6fbc 100644
--- a/include/sys/fs/Makefile.in
+++ b/include/sys/fs/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/include/sys/zfs_vfsops.h b/include/sys/zfs_vfsops.h
index 6d4d713ce..b7badeed8 100644
--- a/include/sys/zfs_vfsops.h
+++ b/include/sys/zfs_vfsops.h
@@ -67,7 +67,8 @@ typedef struct zfs_sb {
boolean_t z_unmounted; /* unmounted */
rrwlock_t z_teardown_lock;
krwlock_t z_teardown_inactive_lock;
- list_t z_all_znodes; /* all vnodes in the fs */
+ list_t z_all_znodes; /* all znodes in the fs */
+ uint64_t z_nr_znodes; /* number of znodes in the fs */
kmutex_t z_znodes_lock; /* lock for z_all_znodes */
struct inode *z_ctldir; /* .zfs directory inode */
boolean_t z_show_ctldir; /* expose .zfs in the root dir */
@@ -185,6 +186,8 @@ extern int zfs_get_zplprop(objset_t *os, zfs_prop_t prop,
extern int zfs_sb_create(const char *name, zfs_sb_t **zsbp);
extern int zfs_sb_setup(zfs_sb_t *zsb, boolean_t mounting);
extern void zfs_sb_free(zfs_sb_t *zsb);
+extern int zfs_sb_prune(struct super_block *sb, unsigned long nr_to_scan,
+ int *objects);
extern int zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting);
extern int zfs_check_global_label(const char *dsname, const char *hexsl);
extern boolean_t zfs_is_readonly(zfs_sb_t *zsb);
diff --git a/include/sys/zpl.h b/include/sys/zpl.h
index 0aacce8bd..2195ec9a3 100644
--- a/include/sys/zpl.h
+++ b/include/sys/zpl.h
@@ -48,6 +48,8 @@ extern const struct file_operations zpl_file_operations;
extern const struct file_operations zpl_dir_file_operations;
/* zpl_super.c */
+extern void zpl_prune_sbs(int64_t bytes_to_scan, void *private);
+
typedef struct zpl_mount_data {
const char *z_osname; /* Dataset name */
void *z_data; /* Mount options string */
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 17f84a548..5929cc468 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libavl/Makefile.in b/lib/libavl/Makefile.in
index 55bb04d9f..9a6ea3a75 100644
--- a/lib/libavl/Makefile.in
+++ b/lib/libavl/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libefi/Makefile.in b/lib/libefi/Makefile.in
index 6e4a83b3c..7abee8cab 100644
--- a/lib/libefi/Makefile.in
+++ b/lib/libefi/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libnvpair/Makefile.in b/lib/libnvpair/Makefile.in
index 60439aece..33d3f3b1d 100644
--- a/lib/libnvpair/Makefile.in
+++ b/lib/libnvpair/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libshare/Makefile.in b/lib/libshare/Makefile.in
index 94ea82e90..67d23d279 100644
--- a/lib/libshare/Makefile.in
+++ b/lib/libshare/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/Makefile.in b/lib/libspl/Makefile.in
index 194679a93..db3499a6d 100644
--- a/lib/libspl/Makefile.in
+++ b/lib/libspl/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/asm-generic/Makefile.in b/lib/libspl/asm-generic/Makefile.in
index a9ffb578c..cae5d5678 100644
--- a/lib/libspl/asm-generic/Makefile.in
+++ b/lib/libspl/asm-generic/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/asm-i386/Makefile.in b/lib/libspl/asm-i386/Makefile.in
index ca6573040..652782e66 100644
--- a/lib/libspl/asm-i386/Makefile.in
+++ b/lib/libspl/asm-i386/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/asm-x86_64/Makefile.in b/lib/libspl/asm-x86_64/Makefile.in
index 2db49b35a..ad6c870dc 100644
--- a/lib/libspl/asm-x86_64/Makefile.in
+++ b/lib/libspl/asm-x86_64/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/Makefile.in b/lib/libspl/include/Makefile.in
index d7a8f52fc..419041afa 100644
--- a/lib/libspl/include/Makefile.in
+++ b/lib/libspl/include/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/ia32/Makefile.in b/lib/libspl/include/ia32/Makefile.in
index b60892865..c0418ee60 100644
--- a/lib/libspl/include/ia32/Makefile.in
+++ b/lib/libspl/include/ia32/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/ia32/sys/Makefile.in b/lib/libspl/include/ia32/sys/Makefile.in
index 36629967e..86b08fd79 100644
--- a/lib/libspl/include/ia32/sys/Makefile.in
+++ b/lib/libspl/include/ia32/sys/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/rpc/Makefile.in b/lib/libspl/include/rpc/Makefile.in
index 68e3c2f12..92529aecf 100644
--- a/lib/libspl/include/rpc/Makefile.in
+++ b/lib/libspl/include/rpc/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/sys/Makefile.in b/lib/libspl/include/sys/Makefile.in
index 6851505dd..09e1ec957 100644
--- a/lib/libspl/include/sys/Makefile.in
+++ b/lib/libspl/include/sys/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/sys/dktp/Makefile.in b/lib/libspl/include/sys/dktp/Makefile.in
index 89c3285e1..84961afae 100644
--- a/lib/libspl/include/sys/dktp/Makefile.in
+++ b/lib/libspl/include/sys/dktp/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/sys/sysevent/Makefile.in b/lib/libspl/include/sys/sysevent/Makefile.in
index de9db421b..5d6a93dbe 100644
--- a/lib/libspl/include/sys/sysevent/Makefile.in
+++ b/lib/libspl/include/sys/sysevent/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libspl/include/util/Makefile.in b/lib/libspl/include/util/Makefile.in
index d7cd17c15..068a2f560 100644
--- a/lib/libspl/include/util/Makefile.in
+++ b/lib/libspl/include/util/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libunicode/Makefile.in b/lib/libunicode/Makefile.in
index f6c8690cd..fbcb32b99 100644
--- a/lib/libunicode/Makefile.in
+++ b/lib/libunicode/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libuutil/Makefile.in b/lib/libuutil/Makefile.in
index d44bba2d6..6507a7ead 100644
--- a/lib/libuutil/Makefile.in
+++ b/lib/libuutil/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libzfs/Makefile.in b/lib/libzfs/Makefile.in
index 29642b1ac..a975a193f 100644
--- a/lib/libzfs/Makefile.in
+++ b/lib/libzfs/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/lib/libzpool/Makefile.in b/lib/libzpool/Makefile.in
index 0e46c1516..5e1fded91 100644
--- a/lib/libzpool/Makefile.in
+++ b/lib/libzpool/Makefile.in
@@ -71,6 +71,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/man/Makefile.in b/man/Makefile.in
index 84c6c1706..1ad3c35fd 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/man/man8/Makefile.in b/man/man8/Makefile.in
index be187c9c0..86e691d2e 100644
--- a/man/man8/Makefile.in
+++ b/man/man8/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index f71c24844..95d14a9e7 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -104,6 +104,14 @@
* protected from simultaneous callbacks from arc_buf_evict()
* and arc_do_user_evicts().
*
+ * It as also possible to register a callback which is run when the
+ * arc_meta_limit is reached and no buffers can be safely evicted. In
+ * this case the arc user should drop a reference on some arc buffers so
+ * they can be reclaimed and the arc_meta_limit honored. For example,
+ * when using the ZPL each dentry holds a references on a znode. These
+ * dentries must be pruned before the arc buffer holding the znode can
+ * be safely evicted.
+ *
* Note that the majority of the performance stats are manipulated
* with atomic operations.
*
@@ -120,14 +128,13 @@
#include <sys/zio.h>
#include <sys/zfs_context.h>
#include <sys/arc.h>
-#include <sys/refcount.h>
#include <sys/vdev.h>
#include <sys/vdev_impl.h>
#ifdef _KERNEL
#include <sys/vmsystm.h>
#include <vm/anon.h>
#include <sys/fs/swapnode.h>
-#include <sys/dnlc.h>
+#include <sys/zpl.h>
#endif
#include <sys/callb.h>
#include <sys/kstat.h>
@@ -141,8 +148,8 @@ extern int zfs_write_limit_shift;
extern uint64_t zfs_write_limit_max;
extern kmutex_t zfs_write_limit_lock;
-#define ARC_REDUCE_DNLC_PERCENT 3
-uint_t arc_reduce_dnlc_percent = ARC_REDUCE_DNLC_PERCENT;
+/* number of bytes to prune from caches when at arc_meta_limit is reached */
+uint_t arc_meta_prune = 1048576;
typedef enum arc_reclaim_strategy {
ARC_RECLAIM_AGGR, /* Aggressive reclaim strategy */
@@ -180,7 +187,7 @@ unsigned long zfs_arc_meta_limit = 0;
int zfs_arc_grow_retry = 0;
int zfs_arc_shrink_shift = 0;
int zfs_arc_p_min_shift = 0;
-int zfs_arc_reduce_dnlc_percent = 0;
+int zfs_arc_meta_prune = 0;
/*
* Note that buffers can be in one of 6 states:
@@ -288,6 +295,7 @@ typedef struct arc_stats {
kstat_named_t arcstat_no_grow;
kstat_named_t arcstat_tempreserve;
kstat_named_t arcstat_loaned_bytes;
+ kstat_named_t arcstat_prune;
kstat_named_t arcstat_meta_used;
kstat_named_t arcstat_meta_limit;
kstat_named_t arcstat_meta_max;
@@ -352,6 +360,7 @@ static arc_stats_t arc_stats = {
{ "arc_no_grow", KSTAT_DATA_UINT64 },
{ "arc_tempreserve", KSTAT_DATA_UINT64 },
{ "arc_loaned_bytes", KSTAT_DATA_UINT64 },
+ { "arc_prune", KSTAT_DATA_UINT64 },
{ "arc_meta_used", KSTAT_DATA_UINT64 },
{ "arc_meta_limit", KSTAT_DATA_UINT64 },
{ "arc_meta_max", KSTAT_DATA_UINT64 },
@@ -481,6 +490,8 @@ struct arc_buf_hdr {
list_node_t b_l2node;
};
+static list_t arc_prune_list;
+static kmutex_t arc_prune_mtx;
static arc_buf_t *arc_eviction_list;
static kmutex_t arc_eviction_mtx;
static arc_buf_hdr_t arc_eviction_hdr;
@@ -1925,6 +1936,48 @@ arc_adjust(void)
}
}
+/*
+ * Request that arc user drop references so that N bytes can be released
+ * from the cache. This provides a mechanism to ensure the arc can honor
+ * the arc_meta_limit and reclaim buffers which are pinned in the cache
+ * by higher layers. (i.e. the zpl)
+ */
+static void
+arc_do_user_prune(int64_t adjustment)
+{
+ arc_prune_func_t *func;
+ void *private;
+ arc_prune_t *cp, *np;
+
+ mutex_enter(&arc_prune_mtx);
+
+ cp = list_head(&arc_prune_list);
+ while (cp != NULL) {
+ func = cp->p_pfunc;
+ private = cp->p_private;
+ np = list_next(&arc_prune_list, cp);
+ refcount_add(&cp->p_refcnt, func);
+ mutex_exit(&arc_prune_mtx);
+
+ if (func != NULL)
+ func(adjustment, private);
+
+ mutex_enter(&arc_prune_mtx);
+
+ /* User removed prune callback concurrently with execution */
+ if (refcount_remove(&cp->p_refcnt, func) == 0) {
+ ASSERT(!list_link_active(&cp->p_node));
+ refcount_destroy(&cp->p_refcnt);
+ kmem_free(cp, sizeof (*cp));
+ }
+
+ cp = np;
+ }
+
+ ARCSTAT_BUMP(arcstat_prune);
+ mutex_exit(&arc_prune_mtx);
+}
+
static void
arc_do_user_evicts(void)
{
@@ -1949,6 +2002,32 @@ arc_do_user_evicts(void)
}
/*
+ * Evict only meta data objects from the cache leaving the data objects.
+ * This is only used to enforce the tunable arc_meta_limit, if we are
+ * unable to evict enough buffers notify the user via the prune callback.
+ */
+void
+arc_adjust_meta(int64_t adjustment, boolean_t may_prune)
+{
+ int64_t delta;
+
+ if (adjustment > 0 && arc_mru->arcs_lsize[ARC_BUFC_METADATA] > 0) {
+ delta = MIN(arc_mru->arcs_lsize[ARC_BUFC_METADATA], adjustment);
+ arc_evict(arc_mru, 0, delta, FALSE, ARC_BUFC_METADATA);
+ adjustment -= delta;
+ }
+
+ if (adjustment > 0 && arc_mfu->arcs_lsize[ARC_BUFC_METADATA] > 0) {
+ delta = MIN(arc_mfu->arcs_lsize[ARC_BUFC_METADATA], adjustment);
+ arc_evict(arc_mfu, 0, delta, FALSE, ARC_BUFC_METADATA);
+ adjustment -= delta;
+ }
+
+ if (may_prune && (adjustment > 0) && (arc_meta_used > arc_meta_limit))
+ arc_do_user_prune(arc_meta_prune);
+}
+
+/*
* Flush all *evictable* data from the cache for the given spa.
* NOTE: this will not touch "active" (i.e. referenced) data.
*/
@@ -2085,24 +2164,6 @@ arc_kmem_reap_now(arc_reclaim_strategy_t strat)
kmem_cache_t *prev_data_cache = NULL;
extern kmem_cache_t *zio_buf_cache[];
extern kmem_cache_t *zio_data_buf_cache[];
-#ifdef _KERNEL
- int retry = 0;
-
- while ((arc_meta_used >= arc_meta_limit) && (retry < 10)) {
- /*
- * We are exceeding our meta-data cache limit.
- * Purge some DNLC entries to release holds on meta-data.
- */
- dnlc_reduce_cache((void *)(uintptr_t)arc_reduce_dnlc_percent);
- retry++;
- }
-#if defined(__i386)
- /*
- * Reclaim unused memory from all kmem caches.
- */
- kmem_reap();
-#endif
-#endif
/*
* An aggressive reclamation will shrink the cache size as well as
@@ -2121,6 +2182,7 @@ arc_kmem_reap_now(arc_reclaim_strategy_t strat)
kmem_cache_reap_now(zio_data_buf_cache[i]);
}
}
+
kmem_cache_reap_now(buf_cache);
kmem_cache_reap_now(hdr_cache);
}
@@ -2131,6 +2193,7 @@ arc_reclaim_thread(void)
clock_t growtime = 0;
arc_reclaim_strategy_t last_reclaim = ARC_RECLAIM_CONS;
callb_cpr_t cpr;
+ int64_t prune;
CALLB_CPR_INIT(&cpr, &arc_reclaim_thr_lock, callb_generic_cpr, FTAG);
@@ -2160,9 +2223,14 @@ arc_reclaim_thread(void)
arc_no_grow = FALSE;
}
- /* Keep meta data usage within limits */
- if (arc_meta_used >= arc_meta_limit)
- arc_kmem_reap_now(ARC_RECLAIM_CONS);
+ /*
+ * Keep meta data usage within limits, arc_shrink() is not
+ * used to avoid collapsing the arc_c value when only the
+ * arc_meta_limit is being exceeded.
+ */
+ prune = (int64_t)arc_meta_used - (int64_t)arc_meta_limit;
+ if (prune > 0)
+ arc_adjust_meta(prune, B_TRUE);
arc_adjust();
@@ -2399,16 +2467,27 @@ arc_get_data_buf(arc_buf_t *buf)
state = (arc_mru->arcs_lsize[type] >= size &&
mfu_space > arc_mfu->arcs_size) ? arc_mru : arc_mfu;
}
+
if ((buf->b_data = arc_evict(state, 0, size, TRUE, type)) == NULL) {
if (type == ARC_BUFC_METADATA) {
buf->b_data = zio_buf_alloc(size);
arc_space_consume(size, ARC_SPACE_DATA);
+
+ /*
+ * If we are unable to recycle an existing meta buffer
+ * signal the reclaim thread. It will notify users
+ * via the prune callback to drop references. The
+ * prune callback in run in the context of the reclaim
+ * thread to avoid deadlocking on the hash_lock.
+ */
+ cv_signal(&arc_reclaim_thr_cv);
} else {
ASSERT(type == ARC_BUFC_DATA);
buf->b_data = zio_data_buf_alloc(size);
ARCSTAT_INCR(arcstat_data_size, size);
atomic_add_64(&arc_size, size);
}
+
ARCSTAT_BUMP(arcstat_recycle_miss);
}
ASSERT(buf->b_data != NULL);
@@ -3021,6 +3100,37 @@ top:
return (0);
}
+arc_prune_t *
+arc_add_prune_callback(arc_prune_func_t *func, void *private)
+{
+ arc_prune_t *p;
+
+ p = kmem_alloc(sizeof(*p), KM_SLEEP);
+ p->p_pfunc = func;
+ p->p_private = private;
+ list_link_init(&p->p_node);
+ refcount_create(&p->p_refcnt);
+
+ mutex_enter(&arc_prune_mtx);
+ refcount_add(&p->p_refcnt, &arc_prune_list);
+ list_insert_head(&arc_prune_list, p);
+ mutex_exit(&arc_prune_mtx);
+
+ return (p);
+}
+
+void
+arc_remove_prune_callback(arc_prune_t *p)
+{
+ mutex_enter(&arc_prune_mtx);
+ list_remove(&arc_prune_list, p);
+ if (refcount_remove(&p->p_refcnt, &arc_prune_list) == 0) {
+ refcount_destroy(&p->p_refcnt);
+ kmem_free(p, sizeof (*p));
+ }
+ mutex_exit(&arc_prune_mtx);
+}
+
void
arc_set_callback(arc_buf_t *buf, arc_evict_func_t *func, void *private)
{
@@ -3598,8 +3708,8 @@ arc_init(void)
if (zfs_arc_p_min_shift > 0)
arc_p_min_shift = zfs_arc_p_min_shift;
- if (zfs_arc_reduce_dnlc_percent > 0)
- arc_reduce_dnlc_percent = zfs_arc_reduce_dnlc_percent;
+ if (zfs_arc_meta_prune > 0)
+ arc_meta_prune = zfs_arc_meta_prune;
/* if kmem_flags are set, lets try to use less memory */
if (kmem_debugging())
@@ -3646,7 +3756,10 @@ arc_init(void)
buf_init();
arc_thread_exit = 0;
+ list_create(&arc_prune_list, sizeof (arc_prune_t),
+ offsetof(arc_prune_t, p_node));
arc_eviction_list = NULL;
+ mutex_init(&arc_prune_mtx, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&arc_eviction_mtx, NULL, MUTEX_DEFAULT, NULL);
bzero(&arc_eviction_hdr, sizeof (arc_buf_hdr_t));
@@ -3674,6 +3787,8 @@ arc_init(void)
void
arc_fini(void)
{
+ arc_prune_t *p;
+
mutex_enter(&arc_reclaim_thr_lock);
#ifdef _KERNEL
spl_unregister_shrinker(&arc_shrinker);
@@ -3693,6 +3808,17 @@ arc_fini(void)
arc_ksp = NULL;
}
+ mutex_enter(&arc_prune_mtx);
+ while ((p = list_head(&arc_prune_list)) != NULL) {
+ list_remove(&arc_prune_list, p);
+ refcount_remove(&p->p_refcnt, &arc_prune_list);
+ refcount_destroy(&p->p_refcnt);
+ kmem_free(p, sizeof (*p));
+ }
+ mutex_exit(&arc_prune_mtx);
+
+ list_destroy(&arc_prune_list);
+ mutex_destroy(&arc_prune_mtx);
mutex_destroy(&arc_eviction_mtx);
mutex_destroy(&arc_reclaim_thr_lock);
cv_destroy(&arc_reclaim_thr_cv);
@@ -4774,6 +4900,8 @@ l2arc_stop(void)
EXPORT_SYMBOL(arc_read);
EXPORT_SYMBOL(arc_buf_remove_ref);
EXPORT_SYMBOL(arc_getbuf_func);
+EXPORT_SYMBOL(arc_add_prune_callback);
+EXPORT_SYMBOL(arc_remove_prune_callback);
module_param(zfs_arc_min, ulong, 0444);
MODULE_PARM_DESC(zfs_arc_min, "Min arc size");
@@ -4784,8 +4912,8 @@ MODULE_PARM_DESC(zfs_arc_max, "Max arc size");
module_param(zfs_arc_meta_limit, ulong, 0444);
MODULE_PARM_DESC(zfs_arc_meta_limit, "Meta limit for arc size");
-module_param(zfs_arc_reduce_dnlc_percent, int, 0444);
-MODULE_PARM_DESC(zfs_arc_reduce_dnlc_percent, "Meta reclaim percentage");
+module_param(zfs_arc_meta_prune, int, 0444);
+MODULE_PARM_DESC(zfs_arc_meta_prune, "Bytes of meta data to prune");
module_param(zfs_arc_grow_retry, int, 0444);
MODULE_PARM_DESC(zfs_arc_grow_retry, "Seconds before growing arc size");
diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c
index a0726e117..fb319a547 100644
--- a/module/zfs/zfs_vfsops.c
+++ b/module/zfs/zfs_vfsops.c
@@ -986,6 +986,26 @@ zfs_root(zfs_sb_t *zsb, struct inode **ipp)
}
EXPORT_SYMBOL(zfs_root);
+#ifdef HAVE_SHRINK
+int
+zfs_sb_prune(struct super_block *sb, unsigned long nr_to_scan, int *objects)
+{
+ zfs_sb_t *zsb = sb->s_fs_info;
+ struct shrinker *shrinker = &sb->s_shrink;
+ struct shrink_control sc = {
+ .nr_to_scan = nr_to_scan,
+ .gfp_mask = GFP_KERNEL,
+ };
+
+ ZFS_ENTER(zsb);
+ *objects = (*shrinker->shrink)(shrinker, &sc);
+ ZFS_EXIT(zsb);
+
+ return (0);
+}
+EXPORT_SYMBOL(zfs_sb_prune);
+#endif /* HAVE_SHRINK */
+
/*
* Teardown the zfs_sb_t::z_os.
*
@@ -1533,6 +1553,7 @@ zfs_init(void)
zfs_znode_init();
dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
register_filesystem(&zpl_fs_type);
+ (void) arc_add_prune_callback(zpl_prune_sbs, NULL);
}
void
diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c
index a35e3b5f2..709ae74f8 100644
--- a/module/zfs/zfs_znode.c
+++ b/module/zfs/zfs_znode.c
@@ -269,6 +269,7 @@ zfs_inode_destroy(struct inode *ip)
mutex_enter(&zsb->z_znodes_lock);
list_remove(&zsb->z_all_znodes, zp);
+ zsb->z_nr_znodes--;
mutex_exit(&zsb->z_znodes_lock);
if (zp->z_acl_cached) {
@@ -401,6 +402,7 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
mutex_enter(&zsb->z_znodes_lock);
list_insert_tail(&zsb->z_all_znodes, zp);
+ zsb->z_nr_znodes++;
membar_producer();
mutex_exit(&zsb->z_znodes_lock);
diff --git a/module/zfs/zpl_super.c b/module/zfs/zpl_super.c
index 650e9c0d3..3abb26a9e 100644
--- a/module/zfs/zpl_super.c
+++ b/module/zfs/zpl_super.c
@@ -199,34 +199,120 @@ zpl_kill_sb(struct super_block *sb)
kill_anon_super(sb);
}
+#ifdef HAVE_SHRINK
+/*
+ * Linux 3.1 - 3.x API
+ *
+ * The Linux 3.1 API introduced per-sb cache shrinkers to replace the
+ * global ones. This allows us a mechanism to cleanly target a specific
+ * zfs file system when the dnode and inode caches grow too large.
+ *
+ * In addition, the 3.0 kernel added the iterate_supers_type() helper
+ * function which is used to safely walk all of the zfs file systems.
+ */
+static void
+zpl_prune_sb(struct super_block *sb, void *arg)
+{
+ int objects = 0;
+ int error;
+
+ error = -zfs_sb_prune(sb, *(unsigned long *)arg, &objects);
+ ASSERT3S(error, <=, 0);
+
+ return;
+}
+
+void
+zpl_prune_sbs(int64_t bytes_to_scan, void *private)
+{
+ unsigned long nr_to_scan = (bytes_to_scan / sizeof(znode_t));
+
+ iterate_supers_type(&zpl_fs_type, zpl_prune_sb, &nr_to_scan);
+ kmem_reap();
+}
+#else
+/*
+ * Linux 2.6.x - 3.0 API
+ *
+ * These are best effort interfaces are provided by the SPL to induce
+ * the Linux VM subsystem to reclaim a fraction of the both dnode and
+ * inode caches. Ideally, we want to just target the zfs file systems
+ * however our only option is to reclaim from them all.
+ */
+void
+zpl_prune_sbs(int64_t bytes_to_scan, void *private)
+{
+ unsigned long nr_to_scan = (bytes_to_scan / sizeof(znode_t));
+
+ shrink_dcache_memory(nr_to_scan, GFP_KERNEL);
+ shrink_icache_memory(nr_to_scan, GFP_KERNEL);
+ kmem_reap();
+}
+#endif /* HAVE_SHRINK */
+
+#ifdef HAVE_NR_CACHED_OBJECTS
+static int
+zpl_nr_cached_objects(struct super_block *sb)
+{
+ zfs_sb_t *zsb = sb->s_fs_info;
+ int nr;
+
+ mutex_enter(&zsb->z_znodes_lock);
+ nr = zsb->z_nr_znodes;
+ mutex_exit(&zsb->z_znodes_lock);
+
+ return (nr);
+}
+#endif /* HAVE_NR_CACHED_OBJECTS */
+
+#ifdef HAVE_FREE_CACHED_OBJECTS
+/*
+ * Attempt to evict some meta data from the cache. The ARC operates in
+ * terms of bytes while the Linux VFS uses objects. Now because this is
+ * just a best effort eviction and the exact values aren't critical so we
+ * extrapolate from an object count to a byte size using the znode_t size.
+ */
+static void
+zpl_free_cached_objects(struct super_block *sb, int nr_to_scan)
+{
+ arc_adjust_meta(nr_to_scan * sizeof(znode_t), B_FALSE);
+}
+#endif /* HAVE_FREE_CACHED_OBJECTS */
+
const struct super_operations zpl_super_operations = {
- .alloc_inode = zpl_inode_alloc,
- .destroy_inode = zpl_inode_destroy,
- .dirty_inode = NULL,
- .write_inode = NULL,
- .drop_inode = NULL,
+ .alloc_inode = zpl_inode_alloc,
+ .destroy_inode = zpl_inode_destroy,
+ .dirty_inode = NULL,
+ .write_inode = NULL,
+ .drop_inode = NULL,
#ifdef HAVE_EVICT_INODE
- .evict_inode = zpl_evict_inode,
+ .evict_inode = zpl_evict_inode,
#else
- .clear_inode = zpl_clear_inode,
- .delete_inode = zpl_inode_delete,
+ .clear_inode = zpl_clear_inode,
+ .delete_inode = zpl_inode_delete,
#endif /* HAVE_EVICT_INODE */
- .put_super = zpl_put_super,
- .write_super = NULL,
- .sync_fs = zpl_sync_fs,
- .statfs = zpl_statfs,
- .remount_fs = zpl_remount_fs,
- .show_options = zpl_show_options,
- .show_stats = NULL,
+ .put_super = zpl_put_super,
+ .write_super = NULL,
+ .sync_fs = zpl_sync_fs,
+ .statfs = zpl_statfs,
+ .remount_fs = zpl_remount_fs,
+ .show_options = zpl_show_options,
+ .show_stats = NULL,
+#ifdef HAVE_NR_CACHED_OBJECTS
+ .nr_cached_objects = zpl_nr_cached_objects,
+#endif /* HAVE_NR_CACHED_OBJECTS */
+#ifdef HAVE_FREE_CACHED_OBJECTS
+ .free_cached_objects = zpl_free_cached_objects,
+#endif /* HAVE_FREE_CACHED_OBJECTS */
};
struct file_system_type zpl_fs_type = {
- .owner = THIS_MODULE,
- .name = ZFS_DRIVER,
+ .owner = THIS_MODULE,
+ .name = ZFS_DRIVER,
#ifdef HAVE_MOUNT_NODEV
- .mount = zpl_mount,
+ .mount = zpl_mount,
#else
- .get_sb = zpl_get_sb,
+ .get_sb = zpl_get_sb,
#endif /* HAVE_MOUNT_NODEV */
- .kill_sb = zpl_kill_sb,
+ .kill_sb = zpl_kill_sb,
};
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index 5115a9e0b..4fdc85b67 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/scripts/zpios-profile/Makefile.in b/scripts/zpios-profile/Makefile.in
index 1c59d7475..339062111 100644
--- a/scripts/zpios-profile/Makefile.in
+++ b/scripts/zpios-profile/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/scripts/zpios-test/Makefile.in b/scripts/zpios-test/Makefile.in
index fb1114530..1adbef8cf 100644
--- a/scripts/zpios-test/Makefile.in
+++ b/scripts/zpios-test/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/scripts/zpool-config/Makefile.in b/scripts/zpool-config/Makefile.in
index 2c4fcb976..c78e79667 100644
--- a/scripts/zpool-config/Makefile.in
+++ b/scripts/zpool-config/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/scripts/zpool-layout/Makefile.in b/scripts/zpool-layout/Makefile.in
index bebd47b8f..59034e069 100644
--- a/scripts/zpool-layout/Makefile.in
+++ b/scripts/zpool-layout/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/udev/Makefile.in b/udev/Makefile.in
index 856d11aaf..6232f65db 100644
--- a/udev/Makefile.in
+++ b/udev/Makefile.in
@@ -69,6 +69,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/udev/rules.d/Makefile.in b/udev/rules.d/Makefile.in
index 37eb4c732..f9a72cfb6 100644
--- a/udev/rules.d/Makefile.in
+++ b/udev/rules.d/Makefile.in
@@ -70,6 +70,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
$(top_srcdir)/config/kernel-security-inode-init.m4 \
$(top_srcdir)/config/kernel-set-nlink.m4 \
+ $(top_srcdir)/config/kernel-shrink.m4 \
$(top_srcdir)/config/kernel-truncate-setsize.m4 \
$(top_srcdir)/config/kernel-xattr-handler.m4 \
$(top_srcdir)/config/kernel.m4 \
diff --git a/zfs_config.h.in b/zfs_config.h.in
index e0f746704..b53ca52d7 100644
--- a/zfs_config.h.in
+++ b/zfs_config.h.in
@@ -90,6 +90,9 @@
/* kernel defines fmode_t */
#undef HAVE_FMODE_T
+/* sops->free_cached_objects() exists */
+#undef HAVE_FREE_CACHED_OBJECTS
+
/* fops->fsync() with range */
#undef HAVE_FSYNC_RANGE
@@ -141,6 +144,9 @@
/* mount_nodev() is available */
#undef HAVE_MOUNT_NODEV
+/* sops->nr_cached_objects() exists */
+#undef HAVE_NR_CACHED_OBJECTS
+
/* open_bdev_exclusive() is available */
#undef HAVE_OPEN_BDEV_EXCLUSIVE
@@ -156,6 +162,9 @@
/* set_nlink() is available */
#undef HAVE_SET_NLINK
+/* struct super_block has s_shrink */
+#undef HAVE_SHRINK
+
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H