Re: rms_rlock with non-sleepable locks held

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Sat, 16 May 2026 10:08:39 UTC
On Sat, May 16, 2026 at 11:47:12AM +0200, Dag-Erling Smørgrav wrote:
> On recent main with a debugging kernel, I am unable to build anything as
> the system slows to a crawl while the console is inundated with stack
> traces:
> 
>     rms_rlock with the following non-sleepable locks held:
>     exclusive sleep mutex kqueue (kqueue) r = 0 (0xfffff8013615cc00) locked @ /usr/src/sys/kern/kern_event.c:2588
>     stack backtrace:
>     #0 0xffffffff805d571c at witness_debugger+0x6c
>     #1 0xffffffff805d7019 at witness_warn+0x4b9
>     #2 0xffffffff8055841f at rms_rlock+0x1f
>     #3 0xffffffff81418f08 at zfs_freebsd_getattr+0xb8
>     #4 0xffffffff808c1ede at VOP_GETATTR_APV+0x4e
>     #5 0xffffffff8065add0 at vn_getsize_locked+0x70
>     #6 0xffffffff806610c2 at filt_vfsread+0x82
>     #7 0xffffffff805018f4 at knote+0xc4
>     #8 0xffffffff80658f2e at vop_open_post+0x3e
>     #9 0xffffffff808c1572 at VOP_OPEN_APV+0x92
>     #10 0xffffffff8066e67b at vn_open_vnode+0x19b
>     #11 0xffffffff8066de18 at vn_open_cred+0x698
>     #12 0xffffffff8066364e at openatfp+0x2be
>     #13 0xffffffff8066336d at sys_openat+0x3d
>     #14 0xffffffff822153a2 at filemon_wrapper_openat+0x12
>     #15 0xffffffff808a05b8 at amd64_syscall+0x168
>     #16 0xffffffff8086f86b at fast_syscall_common+0xf8
> 
> They vary in how they get to knote() but they're all the same from frame
> 7 and up.
> 
> BTW, filt_vfsread() is an excellent argument for VOP_GETSIZE, with
> vn_getsize() falling back to a full VOP_GETATTR() only when the vnode's
> vop table does not provide it, as the size of a ZFS vnode is very easy
> to get:
> 
>     size_t zfs_getsize(vnode_t *vp) { return (VTOZ(vp)->z_size); }
> 
> while a full VOP_GETATTR() is several hundred lines of code.

I already posted the patch below somewhere, but did not get a response.

commit c3a20bdb7caa3628831bf443cfb1e0316e30d3e7
Author: Konstantin Belousov <kib@FreeBSD.org>
Date:   Wed May 13 23:44:45 2026 +0300

    vop_read{,_pgcache}_post(): unlock knote around call into filter
    
    ZFS vop_getattr() needs a sleepable lock.

diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index b3a6e8ce2e02..d19776940bc3 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -6509,7 +6509,7 @@ vop_read_post(void *ap, int rc)
 	struct vop_read_args *a = ap;
 
 	if (!rc) {
-		VFS_KNOTE_LOCKED(a->a_vp, NOTE_READ);
+		VN_KNOTE_LOCKED(a->a_vp, NOTE_READ);
 		INOTIFY(a->a_vp, IN_ACCESS);
 	}
 }
@@ -6520,7 +6520,7 @@ vop_read_pgcache_post(void *ap, int rc)
 	struct vop_read_pgcache_args *a = ap;
 
 	if (rc == 0) {
-		VFS_KNOTE_LOCKED(a->a_vp, NOTE_READ);
+		VN_KNOTE_UNLOCKED(a->a_vp, NOTE_READ);
 		INOTIFY(a->a_vp, IN_ACCESS);
 	}
 }