git: 4f924a786ae0 - main - linker_kldload_busy(): allow recursion
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 28 Nov 2021 08:36:22 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=4f924a786ae08af496dfe55230f8fe1e2ca16150 commit 4f924a786ae08af496dfe55230f8fe1e2ca16150 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-11-12 19:45:06 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-11-28 08:36:09 +0000 linker_kldload_busy(): allow recursion Some drivers recursively loads modules by explicit calls to kldload during initialization, which might occur during kldload. PR: 259748 Reported and tested by: thj Reviewed by: markj Sponsored by: Nvidia networking MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32972 --- 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 bcdbb467e84e..1337d2c0b278 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); }