Re: panic: sbuf_clear makes no sense on sbuf 0xfffff80004234000 with drain

From: Mark Johnston <markj_at_freebsd.org>
Date: Fri, 29 Dec 2023 15:43:17 UTC
On Fri, Dec 29, 2023 at 10:29:57AM +0100, Peter Holm wrote:
> root@mercat1:/tmp # cat sysctl.sh
> #!/bin/sh
> 
> kldstat | grep -q zfs.ko || kldload zfs.ko
> start=`date +%s`
> while [ $((`date +%s` - start)) -lt 180 ]; do
>         for i in `jot 3`; do
>                 sysctl -a > /dev/null 2>&1 &
>         done
>         wait
> done
> kldstat | grep -q zfs.ko && kldunload zfs.ko
> exit 0
> root@mercat1:/tmp # ./sysctl.sh
> ZFS filesystem version: 5
> ZFS storage pool version: features support (5000)
> panic: sbuf_clear makes no sense on sbuf 0xfffff80004234000 with drain
> cpuid = 0
> time = 1703841857
> KDB: stack backtrace:
> db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe016a270960
> vpanic() at vpanic+0x131/frame 0xfffffe016a270a90
> panic() at panic+0x43/frame 0xfffffe016a270af0
> sbuf_clear() at sbuf_clear+0xa8/frame 0xfffffe016a270b00
> sbuf_cpy() at sbuf_cpy+0x56/frame 0xfffffe016a270b20
> spa_taskq_write_param() at spa_taskq_write_param+0x85/frame 0xfffffe016a270bd0 (src/sys/contrib/openzfs/module/zfs/spa.c:1486)
> sysctl_root_handler_locked() at sysctl_root_handler_locked+0x9c/frame 0xfffffe016a270c20
> sysctl_root() at sysctl_root+0x21e/frame 0xfffffe016a270ca0
> userland_sysctl() at userland_sysctl+0x184/frame 0xfffffe016a270d50
> sys___sysctl() at sys___sysctl+0x60/frame 0xfffffe016a270e00
> amd64_syscall() at amd64_syscall+0x153/frame 0xfffffe016a270f30
> fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe016a270f30
> --- syscall (202, FreeBSD ELF64, __sysctl), rip = 0x116eb469819a, rsp = 0x116eb273c6e8, rbp = 0x116eb273c720 ---
> KDB: enter: panic
> [ thread pid 3697 tid 100308 ]
> Stopped at      kdb_enter+0x33: movq    $0,0xe38ff2(%rip)
> db> x/s version
> FreeBSD 15.0-CURRENT #0 main-n267275-4b817fc1f02c: Thu Dec 28 07:42:48 CET 2023
> pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO
> db> 

The patch below fixes the problem for me.  I submitted it upstream here:
https://github.com/openzfs/zfs/pull/15719

diff --git a/sys/contrib/openzfs/module/zfs/spa.c b/sys/contrib/openzfs/module/zfs/spa.c
index a21b0decf6a3..b489266e0556 100644
--- a/sys/contrib/openzfs/module/zfs/spa.c
+++ b/sys/contrib/openzfs/module/zfs/spa.c
@@ -1460,11 +1460,12 @@ spa_taskq_read_param(ZFS_MODULE_PARAM_ARGS)
 	int err = 0;
 
 	if (req->newptr == NULL) {
+		struct sbuf s;
 		int len = spa_taskq_param_get(ZIO_TYPE_READ, buf);
-		struct sbuf *s = sbuf_new_for_sysctl(NULL, NULL, len+1, req);
-		sbuf_cpy(s, buf);
-		err = sbuf_finish(s);
-		sbuf_delete(s);
+
+		(void) sbuf_new_for_sysctl(&s, buf, len + 1, req);
+		err = sbuf_finish(&s);
+		sbuf_delete(&s);
 		return (err);
 	}
 
@@ -1481,11 +1482,12 @@ spa_taskq_write_param(ZFS_MODULE_PARAM_ARGS)
 	int err = 0;
 
 	if (req->newptr == NULL) {
+		struct sbuf s;
 		int len = spa_taskq_param_get(ZIO_TYPE_WRITE, buf);
-		struct sbuf *s = sbuf_new_for_sysctl(NULL, NULL, len+1, req);
-		sbuf_cpy(s, buf);
-		err = sbuf_finish(s);
-		sbuf_delete(s);
+
+		(void) sbuf_new_for_sysctl(&s, buf, len + 1, req);
+		err = sbuf_finish(&s);
+		sbuf_delete(&s);
 		return (err);
 	}