The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4f924a786ae08af496dfe55230f8fe1e2ca16150

commit 4f924a786ae08af496dfe55230f8fe1e2ca16150
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2021-11-12 19:45:06 +0000
Commit:     Konstantin Belousov <[email protected]>
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);
 }
 

Reply via email to