A self-referencing nullfs mount over a tmpfs filesystem succeeds and is usable, but unmounting it causes a kernel panic. The panic is reproducible when the lower filesystem is tmpfs. I could not reproduce it with UFS. root@freebsd:/tmp # mount -t tmpfs tmpfs /rt root@freebsd:/tmp # cd /rt root@freebsd:/rt # mkdir -p root/a/b root@freebsd:/rt # find . [...] root@freebsd:/rt # mount -t nullfs root root/a/b root@freebsd:/rt # find root [...] root@freebsd:/rt # cd root/a/b root@freebsd:/rt/root/a/b # touch test root@freebsd:/rt/root/a/b # cd .. root@freebsd:/rt/root/a # touch pouet root@freebsd:/rt/root/a # cd .. root@freebsd:/rt/root # ls a test root@freebsd:/rt/root # cd .. root@freebsd:/rt # umount root/a/b panic: lockmgr_xlock_hard: recursing on non recursive lockmgr 0xfffff80023a38750 @ /home/pkgbuild/worktrees/main/sys/fs/nullfs/null_vn0 [details at the end of the message] == on 15.1-RELEASE-p2 == panic: lockmgr_xlock_hard: recursing on non recursive lockmgr 0xfffff80062222228 @ /usr/src/sys/fs/nullfs/null_vnops.c:810 cpuid = 0 time = 1785436428 KDB: stack backtrace: #0 0xffffffff80bd69cd at kdb_backtrace+0x5d #1 0xffffffff80b87526 at vpanic+0x136 #2 0xffffffff80b873e3 at panic+0x43 #3 0xffffffff80b5694c at lockmgr_xlock_hard+0xac #4 0xffffffff82c20ffc at null_lock+0xdc #5 0xffffffff80c90827 at _vn_lock+0x47 #6 0xffffffff80c78b3f at vflush+0x14f #7 0xffffffff82c1fb90 at nullfs_unmount+0x50 #8 0xffffffff80c6df69 at dounmount+0x789 #9 0xffffffff80c6d76e at kern_unmount+0x31e #10 0xffffffff81099606 at amd64_syscall+0x126 #11 0xffffffff8106fdab at fast_syscall_common+0xf8 Uptime: 2m4s Automatic reboot in 15 seconds - press a key on the console to abort == on 16.0-CURRENT == root@freebsd:/tmp # sysctl kern.version kern.version: FreeBSD 16.0-CURRENT main-n287806-fdce3830d9a6 GENERIC root@freebsd:/tmp # freebsd-version -u 16.0-CURRENT panic: lockmgr_xlock_hard: recursing on non recursive lockmgr 0xfffff80023a38750 @ /home/pkgbuild/worktrees/main/sys/fs/nullfs/null_vn0 cpuid = 0 time = 1785437841 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x36/frame 0xfffffe00d466a780 vpanic() at vpanic+0x149/frame 0xfffffe00d466a8b0 panic() at panic+0x43/frame 0xfffffe00d466a910 lockmgr_xlock_hard() at lockmgr_xlock_hard+0xfc/frame 0xfffffe00d466a9c0 VOP_LOCK1_APV() at VOP_LOCK1_APV+0x32/frame 0xfffffe00d466a9e0 null_lock() at null_lock+0x174/frame 0xfffffe00d466aa40 VOP_LOCK1_APV() at VOP_LOCK1_APV+0x32/frame 0xfffffe00d466aa60 _vn_lock() at _vn_lock+0x62/frame 0xfffffe00d466aac0 vflush() at vflush+0xf9/frame 0xfffffe00d466ac10 nullfs_unmount() at nullfs_unmount+0x50/frame 0xfffffe00d466ac60 dounmount() at dounmount+0x67d/frame 0xfffffe00d466acd0 kern_unmount() at kern_unmount+0x379/frame 0xfffffe00d466adf0 amd64_syscall() at amd64_syscall+0x17c/frame 0xfffffe00d466af30 fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe00d466af30 --- syscall (22, FreeBSD ELF64, unmount), rip = 0x345dadb091ea, rsp = 0x345dabd588e8, rbp = 0x345dabd58e20 --- KDB: enter: panic [ thread pid 1454 tid 100147 ] Stopped at kdb_enter+0x33: movq $0,0x11813e2(%rip) db> show locks exclusive lockmgr tmpfs (tmpfs) r = 0 (0xfffff80023a38750) locked @ /home/pkgbuild/worktrees/main/sys/kern/vfs_mount.c:2308 db> show thread Thread 100147 at 0xfffff800029ae000: proc (pid 1454): 0xfffffe00c34c8000 name: umount pcb: 0xfffff800029ae550 stack: 0xfffffe00d4667000-0xfffffe00d466afff flags: 0x4 pflags: 0x100 state: RUNNING (CPU 0) priority: 56 container lock: sched lock 0 (0xffffffff825b8440) last voluntary switch: 0.000 s ago
https://reviews.freebsd.org/D58567
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=9f5c4ef32812afb4573a278e6eafe5040f839d13 commit 9f5c4ef32812afb4573a278e6eafe5040f839d13 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-07-31 04:12:17 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-08-07 09:09:50 +0000 dounmount(9): temporarily enable recursion for the covered vnode lock For some complex nullfs mount configurations, it is possible to get the covered vnode lock for the mount shared with some inside-mount vnode lock. Then at unmount time, vflush() would recurse on the covered vnode lock when reclaiming the vnode. Work around it, by temprorarily allowing recursion on the covered vnode lock. Disable recursion after the unmount if it was not enabled before. PR: 297174 Reviewed by: jah Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D58567 sys/kern/vfs_mount.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-)
A commit in branch stable/15 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=42dbbaf748ea18195174854dae0831180af3e256 commit 42dbbaf748ea18195174854dae0831180af3e256 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-07-31 04:12:17 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-08-13 00:34:41 +0000 dounmount(9): temporarily enable recursion for the covered vnode lock PR: 297174 (cherry picked from commit 9f5c4ef32812afb4573a278e6eafe5040f839d13) sys/kern/vfs_mount.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-)