git: 2c52eba4f46e - stable/13 - linker_kldload_busy(): allow recursion
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 05 Dec 2021 01:03:25 UTC
The branch stable/13 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=2c52eba4f46e2cc9a4fda3a9e6e81e06fb8daf57 commit 2c52eba4f46e2cc9a4fda3a9e6e81e06fb8daf57 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-11-12 19:45:06 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-12-05 01:02:57 +0000 linker_kldload_busy(): allow recursion PR: 259748 (cherry picked from commit 4f924a786ae08af496dfe55230f8fe1e2ca16150) --- sys/kern/kern_linker.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index cb5d587bfbbc..a10c9a0cea7e 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -106,7 +106,8 @@ MALLOC_DEFINE(M_LINKER, "linker", "kernel linker"); linker_file_t linker_kernel_file; static struct sx kld_sx; /* kernel linker lock */ -static bool kld_busy; +static u_int kld_busy; +static struct thread *kld_busy_owner; /* * Load counter used by clients to determine if a linker file has been @@ -1065,7 +1066,9 @@ linker_kldload_busy(int flags) if ((flags & LINKER_UB_LOCKED) == 0) sx_xlock(&kld_sx); - while (kld_busy) { + while (kld_busy > 0) { + if (kld_busy_owner == curthread) + break; error = sx_sleep(&kld_busy, &kld_sx, (flags & LINKER_UB_PCATCH) != 0 ? PCATCH : 0, "kldbusy", 0); @@ -1075,7 +1078,8 @@ linker_kldload_busy(int flags) return (error); } } - kld_busy = true; + kld_busy++; + kld_busy_owner = curthread; if ((flags & LINKER_UB_UNLOCK) != 0) sx_xunlock(&kld_sx); return (0); @@ -1090,9 +1094,15 @@ linker_kldload_unbusy(int flags) if ((flags & LINKER_UB_LOCKED) == 0) sx_xlock(&kld_sx); - MPASS(kld_busy); - kld_busy = false; - wakeup(&kld_busy); + MPASS(kld_busy > 0); + if (kld_busy_owner != curthread) + panic("linker_kldload_unbusy done by not owning thread %p", + kld_busy_owner); + kld_busy--; + if (kld_busy == 0) { + kld_busy_owner = NULL; + wakeup(&kld_busy); + } sx_xunlock(&kld_sx); }