Re: userret: returning with the following locks held
Zhenlei Huang <[email protected]>
| Newsgroups | gmane.os.freebsd.current |
|---|---|
| Message-ID | <[email protected]> |
> On Mar 19, 2026, at 2:01 AM, Konstantin Belousov <[email protected]> wrote: > > On Wed, Mar 18, 2026 at 05:36:00PM +0800, Zhenlei Huang wrote: >> Hi, >> >> While I'm working on the if_detach() / if_vmove() racing issue and I wrote >> a test and try to repeat the race condition and got this assert panic, >> >> ``` >> <6>epair1b: link state changed to UP >> userret: returning with the following locks held: >> exclusive sx ifnet_detach_sx (ifnet_detach_sx) r = 1 (0xffffffff83ab75e0) locked @ /home/zlei/freebsd-src/sys/net/if.c:1286 >> panic: witness_warn >> cpuid = 2 >> time = 1773824038 >> KDB: stack backtrace: >> db_trace_self_wrapper() at db_trace_self_wrapper+0xa5/frame 0xfffffe00ec001710 >> kdb_backtrace() at kdb_backtrace+0xc6/frame 0xfffffe00ec001870 >> vpanic() at vpanic+0x214/frame 0xfffffe00ec001a10 >> panic() at panic+0xb5/frame 0xfffffe00ec001ad0 >> witness_warn() at witness_warn+0x7f7/frame 0xfffffe00ec001c30 >> userret() at userret+0x11c/frame 0xfffffe00ec001d10 >> amd64_syscall() at amd64_syscall+0x694/frame 0xfffffe00ec001f30 >> fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe00ec001f30 >> --- syscall (19, FreeBSD ELF64, compat.lseek), rip = 0xfd288de65ba, rsp = 0xfd284aad4b8, rbp = 0xfd284aad500 --- >> Uptime: 29m8s >> Dumping 1355 out of 16137 MB:..2%..11%..21%..31%..41%..51%..61%..71%..81%..91% >> ``` >> >> The line 1286 of sys/net/if.c is ( my WIP revision ), >> >> ``` >> 1250 static int >> 1251 if_vmove_reclaim(struct thread *td, char *ifname, int jid) >> 1252 { >> ... >> 1282 /* Get interface back from child jail/vnet. */ >> 1283 found = if_unlink_ifnet(ifp, true); >> 1284 MPASS(found); >> 1285 sx_xlock(&ifnet_detach_sxlock); >> 1286 if_vmove(ifp, vnet_dst); >> 1287 sx_xunlock(&ifnet_detach_sxlock); >> 1288 >> 1289 /* Report the new if_xname back to the userland. */ >> 1290 sprintf(ifname, "%s", ifp->if_xname); >> 1291 >> 1292 prison_free(pr); >> 1293 CURVNET_RESTORE(); >> 1294 return (0); >> 1295 } >> ``` >> >> That puzzled me a lot. The current thread only reaches to `if_vmove()` , how does it happen to userret() ? >> >> Is that witness warn is false report ? > > I doubt that this is false report. > > userret() is the common code that prepares thread for return from kernel > to usermode. As part of the preparation, it checks that no locks is > left owned by the thread. What you see is the result of the failing > check. > > In other words, you have some syscall that locked a lock, did not released > it, then returned. The layer that manages return to userspace caught the > issue. Thanks ! I'll take care of the locking issue ( syscall returned without lock released ). I'll report back if I re-encounter this issue. Best regards, Zhenlei