tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

ZFS tunable parameters



Hi,

I looked into exposing ZFS tunables through sysctl and it seems
straightforward. Despite being under "dist" I am not sure if this is true 
upstream, so the patch is directly on arc.c (and I think it'd be tricky to
implement otherwise).

I tested arc_min and arc_max, and it seems like changes do have an effect
(e.g. on c, c_max). Additionally tested arc_free_target and it does have
an effect also.

Here are the new sysctl values on boot on a 8G system:

    vfs.zfs.arc_min = 392903680
    vfs.zfs.arc_max = 3143229440
    vfs.zfs.arc_average_blocksize = 8192
    vfs.zfs.arc_shrink_shift = 7
    vfs.zfs.compressed_arc_enable = 1
    vfs.zfs.arc_meta_limit = 785807360
    vfs.zfs.arc_meta_min = 0
    vfs.zfs.arc_free_target = 682


Cc'ing kre and martin because you worked on the ZFS source last. Hope
somebody finds this useful and I'd appreciate any feedback!

S.


Index: external/cddl/osnet/dist/uts/common/fs/zfs/arc.c
===================================================================
RCS file: /cvsroot/src/external/cddl/osnet/dist/uts/common/fs/zfs/arc.c,v
retrieving revision 1.23
diff -u -r1.23 arc.c
--- external/cddl/osnet/dist/uts/common/fs/zfs/arc.c	3 May 2026 22:41:40 -0000	1.23
+++ external/cddl/osnet/dist/uts/common/fs/zfs/arc.c	20 Jun 2026 12:56:45 -0000
@@ -288,13 +288,16 @@
 #define	freemem		uvm_availmem(false)
 #define	minfree		uvmexp.freemin
 #define	desfree		uvmexp.freetarg
-#define	zfs_arc_free_target desfree
+#define	vm_pageout_wakeup_thresh desfree
 #define	lotsfree	(desfree * 2)
 #define	availrmem	desfree
 #define	swapfs_minfree	0
 #define	swapfs_reserve	0
 #undef curproc
 #define	curproc		curlwp
+#define vm_cnt uvmexp
+#define v_page_count npages
+#define SYSCTL_HANDLER_ARGS SYSCTLFN_ARGS
 
 static void	*zio_arena;
 
@@ -393,7 +396,7 @@
 
 boolean_t zfs_compressed_arc_enabled = B_TRUE;
 
-#if defined(__FreeBSD__) && defined(_KERNEL)
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(_KERNEL)
 u_int zfs_arc_free_target = 0;
 
 static int sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS);
@@ -407,6 +410,7 @@
 
 	zfs_arc_free_target = vm_pageout_wakeup_thresh;
 }
+#ifdef __FreeBSD__
 SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY,
     arc_free_target_init, NULL);
 
@@ -435,17 +439,98 @@
     CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RW, 0, sizeof(u_int),
     sysctl_vfs_zfs_arc_free_target, "IU",
     "Desired number of free pages below which ARC triggers reclaim");
+#elifdef __NetBSD__
+SYSCTL_SETUP(zfs_sysctl_init, "zfs sysctl")
+{
+      const struct sysctlnode *rnode;
+
+      sysctl_createv(clog, 0, NULL, &rnode,
+          CTLFLAG_PERMANENT,
+          CTLTYPE_NODE, "zfs",
+          SYSCTL_DESCR("ZFS vfs options"),
+          NULL, 0, NULL, 0,
+          CTL_VFS, CTL_CREATE, CTL_EOL);
+
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+          CTLTYPE_QUAD, "arc_min",
+          SYSCTL_DESCR("Minimum ARC size"),
+          sysctl_vfs_zfs_arc_min, 0, &zfs_arc_min, 0,
+          CTL_CREATE, CTL_EOL);
+
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+          CTLTYPE_QUAD, "arc_max",
+          SYSCTL_DESCR("Maximum ARC size"),
+          sysctl_vfs_zfs_arc_max, 0, &zfs_arc_max, 0,
+          CTL_CREATE, CTL_EOL);
+
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READONLY,
+          CTLTYPE_QUAD, "arc_average_blocksize",
+          SYSCTL_DESCR("ARC average blocksize"),
+          NULL, 0, &zfs_arc_average_blocksize, 0,
+          CTL_CREATE, CTL_EOL);
+
+      zfs_arc_shrink_shift = arc_shrink_shift;
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+          CTLTYPE_INT, "arc_shrink_shift",
+          SYSCTL_DESCR("log2(fraction of arc to reclaim)"),
+          NULL, 0, &zfs_arc_shrink_shift, 0,
+          CTL_CREATE, CTL_EOL);
+
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READONLY,
+          CTLTYPE_INT, "compressed_arc_enable",
+          SYSCTL_DESCR("Enable compressed ARC"),
+          NULL, 0, &zfs_compressed_arc_enabled, 0,
+          CTL_CREATE, CTL_EOL);
+
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+          CTLTYPE_QUAD, "arc_meta_limit",
+          SYSCTL_DESCR("ARC metadata limit"),
+          sysctl_vfs_zfs_arc_meta_limit, 0, &zfs_arc_meta_limit, 0,
+          CTL_CREATE, CTL_EOL);
+
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+          CTLTYPE_QUAD, "arc_meta_min",
+          SYSCTL_DESCR("Minimum ARC metadata size"),
+          NULL, 0, &zfs_arc_meta_min, 0,
+          CTL_CREATE, CTL_EOL);
+
+      arc_free_target_init(NULL);
+      sysctl_createv(clog, 0, &rnode, NULL,
+          CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+          CTLTYPE_INT, "arc_free_target",
+          SYSCTL_DESCR("Desired number of free pages below which ARC triggers reclaim"),
+          sysctl_vfs_zfs_arc_free_target, 0, &zfs_arc_free_target, 0,
+          CTL_CREATE, CTL_EOL);
+}
+#endif
 
 static int
 sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS)
 {
+#ifdef __NetBSD__
+	struct sysctlnode node;
+#endif
 	u_int val;
 	int err;
 
 	val = zfs_arc_free_target;
+#ifdef __FreeBSD__
 	err = sysctl_handle_int(oidp, &val, 0, req);
 	if (err != 0 || req->newptr == NULL)
+#else
+	node = *rnode;
+	node.sysctl_data = &val;
+  err = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (err || newp == NULL)
 		return (err);
+#endif
 
 	if (val < minfree)
 		return (EINVAL);
@@ -457,6 +542,7 @@
 	return (0);
 }
 
+#ifdef __FreeBSD__
 /*
  * Must be declared here, before the definition of corresponding kstat
  * macro which uses the same names will confuse the compiler.
@@ -466,6 +552,7 @@
     sysctl_vfs_zfs_arc_meta_limit, "QU",
     "ARC metadata limit");
 #endif
+#endif
 
 /*
  * Note that buffers can be in one of 6 states:
@@ -1072,17 +1159,28 @@
 	l1arc_buf_hdr_t		b_l1hdr;
 };
 
-#if defined(__FreeBSD__) && defined(_KERNEL)
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(_KERNEL)
 static int
 sysctl_vfs_zfs_arc_meta_limit(SYSCTL_HANDLER_ARGS)
 {
+#ifdef __NetBSD__
+	struct sysctlnode node;
+#endif
 	uint64_t val;
 	int err;
 
 	val = arc_meta_limit;
+#ifdef __FreeBSD__
 	err = sysctl_handle_64(oidp, &val, 0, req);
 	if (err != 0 || req->newptr == NULL)
 		return (err);
+#elifdef __NetBSD__
+	node = *rnode;
+	node.sysctl_data = &val;
+	err = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (err || newp == NULL)
+		return (err);
+#endif
 
         if (val <= 0 || val > arc_c_max)
 		return (EINVAL);
@@ -1094,14 +1192,26 @@
 static int
 sysctl_vfs_zfs_arc_max(SYSCTL_HANDLER_ARGS)
 {
+#ifdef __NetBSD__
+	struct sysctlnode node;
+#endif
 	uint64_t val;
 	int err;
 
 	val = zfs_arc_max;
+#ifdef __FreeBSD__
 	err = sysctl_handle_64(oidp, &val, 0, req);
 	if (err != 0 || req->newptr == NULL)
 		return (err);
 
+#elifdef __NetBSD__
+	node = *rnode;
+	node.sysctl_data = &val;
+	err = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (err || newp == NULL)
+		return (err);
+#endif
+
 	if (zfs_arc_max == 0) {
 		/* Loader tunable so blindly set */
 		zfs_arc_max = val;
@@ -1137,13 +1247,24 @@
 static int
 sysctl_vfs_zfs_arc_min(SYSCTL_HANDLER_ARGS)
 {
+#ifdef __NetBSD__
+	struct sysctlnode node;
+#endif
 	uint64_t val;
 	int err;
 
 	val = zfs_arc_min;
+#ifdef __FreeBSD__
 	err = sysctl_handle_64(oidp, &val, 0, req);
 	if (err != 0 || req->newptr == NULL)
 		return (err);
+#elifdef __NetBSD__
+	node = *rnode;
+	node.sysctl_data = &val;
+  err = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (err || newp == NULL)
+		return (err);
+#endif
 
 	if (zfs_arc_min == 0) {
 		/* Loader tunable so blindly set */



Home | Main Index | Thread Index | Old Index