Author: smh
Date: Wed Jun 29 07:55:45 2016
New Revision: 302265
URL: https://svnweb.freebsd.org/changeset/base/302265

Log:
  Allow ZFS ARC min / max to be tuned at runtime
  
  Prior to this change ZFS ARC min / max could only be changed using
  boot time tunables, this allows the values to be tuned at runtime
  using the sysctls:
  * vfs.zfs.arc_max
  * vfs.zfs.arc_min
  
  When adjusting ZFS ARC minimum the memory used  will only reduce
  to the new minimum given memory pressure.
  
  Reviewed by:  allanjude
  Approved by:  re (gjb)
  MFC after:    2 weeks
  Relnotes:     yes
  Sponsored by: Multiplay
  Differential Revision:        https://reviews.freebsd.org/D5907

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c   Wed Jun 29 
07:00:15 2016        (r302264)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c   Wed Jun 29 
07:55:45 2016        (r302265)
@@ -238,10 +238,15 @@ int zfs_disable_dup_eviction = 0;
 uint64_t zfs_arc_average_blocksize = 8 * 1024; /* 8KB */
 u_int zfs_arc_free_target = 0;
 
+/* Absolute min for arc min / max is 16MB. */
+static uint64_t arc_abs_min = 16 << 20;
+
 static int sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS);
 static int sysctl_vfs_zfs_arc_meta_limit(SYSCTL_HANDLER_ARGS);
+static int sysctl_vfs_zfs_arc_max(SYSCTL_HANDLER_ARGS);
+static int sysctl_vfs_zfs_arc_min(SYSCTL_HANDLER_ARGS);
 
-#ifdef _KERNEL
+#if defined(__FreeBSD__) && defined(_KERNEL)
 static void
 arc_free_target_init(void *unused __unused)
 {
@@ -255,10 +260,10 @@ TUNABLE_QUAD("vfs.zfs.arc_meta_limit", &
 TUNABLE_QUAD("vfs.zfs.arc_meta_min", &zfs_arc_meta_min);
 TUNABLE_INT("vfs.zfs.arc_shrink_shift", &zfs_arc_shrink_shift);
 SYSCTL_DECL(_vfs_zfs);
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, arc_max, CTLFLAG_RDTUN, &zfs_arc_max, 0,
-    "Maximum ARC size");
-SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, arc_min, CTLFLAG_RDTUN, &zfs_arc_min, 0,
-    "Minimum ARC size");
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_max, CTLTYPE_U64 | CTLFLAG_RWTUN,
+    0, sizeof(uint64_t), sysctl_vfs_zfs_arc_max, "QU", "Maximum ARC size");
+SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_min, CTLTYPE_U64 | CTLFLAG_RWTUN,
+    0, sizeof(uint64_t), sysctl_vfs_zfs_arc_min, "QU", "Minimum ARC size");
 SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, arc_average_blocksize, CTLFLAG_RDTUN,
     &zfs_arc_average_blocksize, 0,
     "ARC average blocksize");
@@ -884,7 +889,7 @@ struct arc_buf_hdr {
        l1arc_buf_hdr_t         b_l1hdr;
 };
 
-#ifdef _KERNEL
+#if defined(__FreeBSD__) && defined(_KERNEL)
 static int
 sysctl_vfs_zfs_arc_meta_limit(SYSCTL_HANDLER_ARGS)
 {
@@ -902,6 +907,70 @@ sysctl_vfs_zfs_arc_meta_limit(SYSCTL_HAN
        arc_meta_limit = val;
        return (0);
 }
+
+static int
+sysctl_vfs_zfs_arc_max(SYSCTL_HANDLER_ARGS)
+{
+       uint64_t val;
+       int err;
+
+       val = zfs_arc_max;
+       err = sysctl_handle_64(oidp, &val, 0, req);
+       if (err != 0 || req->newptr == NULL)
+               return (err);
+
+       if (val < arc_abs_min || val > kmem_size())
+               return (EINVAL);
+       if (val < arc_c_min)
+               return (EINVAL);
+       if (zfs_arc_meta_limit > 0 && val < zfs_arc_meta_limit)
+               return (EINVAL);
+
+       arc_c_max = val;
+
+       arc_c = arc_c_max;
+        arc_p = (arc_c >> 1);
+
+       if (zfs_arc_meta_limit == 0) {
+               /* limit meta-data to 1/4 of the arc capacity */
+               arc_meta_limit = arc_c_max / 4;
+       }
+
+       /* if kmem_flags are set, lets try to use less memory */
+       if (kmem_debugging())
+               arc_c = arc_c / 2;
+
+       zfs_arc_max = arc_c;
+
+       return (0);
+}
+
+static int
+sysctl_vfs_zfs_arc_min(SYSCTL_HANDLER_ARGS)
+{
+       uint64_t val;
+       int err;
+
+       val = zfs_arc_min;
+       err = sysctl_handle_64(oidp, &val, 0, req);
+       if (err != 0 || req->newptr == NULL)
+               return (err);
+
+       if (val < arc_abs_min || val > arc_c_max)
+               return (EINVAL);
+
+       arc_c_min = val;
+
+       if (zfs_arc_meta_min == 0)
+                arc_meta_min = arc_c_min / 2;
+
+       if (arc_c < arc_c_min)
+                arc_c = arc_c_min;
+
+       zfs_arc_min = arc_c_min;
+
+       return (0);
+}
 #endif
 
 static arc_buf_t *arc_eviction_list;
@@ -5385,8 +5454,8 @@ arc_init(void)
        arc_c = MIN(arc_c, vmem_size(heap_arena, VMEM_ALLOC | VMEM_FREE) / 8);
 #endif
 #endif /* illumos */
-       /* set min cache to 1/32 of all memory, or 16MB, whichever is more */
-       arc_c_min = MAX(arc_c / 4, 16 << 20);
+       /* set min cache to 1/32 of all memory, or arc_abs_min, whichever is 
more */
+       arc_c_min = MAX(arc_c / 4, arc_abs_min);
        /* set max to 1/2 of all memory, or all but 1GB, whichever is more */
        if (arc_c * 8 >= 1 << 30)
                arc_c_max = (arc_c * 8) - (1 << 30);
@@ -5407,11 +5476,11 @@ arc_init(void)
 #ifdef _KERNEL
        /*
         * Allow the tunables to override our calculations if they are
-        * reasonable (ie. over 16MB)
+        * reasonable.
         */
-       if (zfs_arc_max > 16 << 20 && zfs_arc_max < kmem_size())
+       if (zfs_arc_max > arc_abs_min && zfs_arc_max < kmem_size())
                arc_c_max = zfs_arc_max;
-       if (zfs_arc_min > 16 << 20 && zfs_arc_min <= arc_c_max)
+       if (zfs_arc_min > arc_abs_min && zfs_arc_min <= arc_c_max)
                arc_c_min = zfs_arc_min;
 #endif
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c      Wed Jun 
29 07:00:15 2016        (r302264)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c      Wed Jun 
29 07:55:45 2016        (r302265)
@@ -49,8 +49,8 @@
 #include <sys/dsl_userhold.h>
 
 #if defined(__FreeBSD__) && defined(_KERNEL)
-#include <sys/sysctl.h>
 #include <sys/types.h>
+#include <sys/sysctl.h>
 #endif
 
 /*
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to