Author: markj
Date: Sat Aug 24 21:08:55 2013
New Revision: 254811
URL: http://svnweb.freebsd.org/changeset/base/254811

Log:
  Set things up so that linker_file_lookup_set() is always called with the
  linker lock held. This makes it possible to call it from a kld event handler
  with the shared lock held.
  
  Reviewed by:  jhb

Modified:
  head/sys/kern/kern_linker.c

Modified: head/sys/kern/kern_linker.c
==============================================================================
--- head/sys/kern/kern_linker.c Sat Aug 24 21:07:04 2013        (r254810)
+++ head/sys/kern/kern_linker.c Sat Aug 24 21:08:55 2013        (r254811)
@@ -188,6 +188,8 @@ linker_file_sysinit(linker_file_t lf)
        KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
            lf->filename));
 
+       sx_assert(&kld_sx, SA_XLOCKED);
+
        if (linker_file_lookup_set(lf, "sysinit_set", &start, &stop, NULL) != 0)
                return;
        /*
@@ -213,6 +215,7 @@ linker_file_sysinit(linker_file_t lf)
         * Traverse the (now) ordered list of system initialization tasks.
         * Perform each task, and continue on to the next task.
         */
+       sx_xunlock(&kld_sx);
        mtx_lock(&Giant);
        for (sipp = start; sipp < stop; sipp++) {
                if ((*sipp)->subsystem == SI_SUB_DUMMY)
@@ -222,6 +225,7 @@ linker_file_sysinit(linker_file_t lf)
                (*((*sipp)->func)) ((*sipp)->udata);
        }
        mtx_unlock(&Giant);
+       sx_xlock(&kld_sx);
 }
 
 static void
@@ -232,6 +236,8 @@ linker_file_sysuninit(linker_file_t lf)
        KLD_DPF(FILE, ("linker_file_sysuninit: calling SYSUNINITs for %s\n",
            lf->filename));
 
+       sx_assert(&kld_sx, SA_XLOCKED);
+
        if (linker_file_lookup_set(lf, "sysuninit_set", &start, &stop,
            NULL) != 0)
                return;
@@ -259,6 +265,7 @@ linker_file_sysuninit(linker_file_t lf)
         * Traverse the (now) ordered list of system initialization tasks.
         * Perform each task, and continue on to the next task.
         */
+       sx_xunlock(&kld_sx);
        mtx_lock(&Giant);
        for (sipp = start; sipp < stop; sipp++) {
                if ((*sipp)->subsystem == SI_SUB_DUMMY)
@@ -268,6 +275,7 @@ linker_file_sysuninit(linker_file_t lf)
                (*((*sipp)->func)) ((*sipp)->udata);
        }
        mtx_unlock(&Giant);
+       sx_xlock(&kld_sx);
 }
 
 static void
@@ -279,13 +287,17 @@ linker_file_register_sysctls(linker_file
            ("linker_file_register_sysctls: registering SYSCTLs for %s\n",
            lf->filename));
 
+       sx_assert(&kld_sx, SA_XLOCKED);
+
        if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
                return;
 
+       sx_xunlock(&kld_sx);
        sysctl_lock();
        for (oidp = start; oidp < stop; oidp++)
                sysctl_register_oid(*oidp);
        sysctl_unlock();
+       sx_xlock(&kld_sx);
 }
 
 static void
@@ -296,13 +308,17 @@ linker_file_unregister_sysctls(linker_fi
        KLD_DPF(FILE, ("linker_file_unregister_sysctls: unregistering SYSCTLs"
            " for %s\n", lf->filename));
 
+       sx_assert(&kld_sx, SA_XLOCKED);
+
        if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
                return;
 
+       sx_xunlock(&kld_sx);
        sysctl_lock();
        for (oidp = start; oidp < stop; oidp++)
                sysctl_unregister_oid(*oidp);
        sysctl_unlock();
+       sx_xlock(&kld_sx);
 }
 
 static int
@@ -315,6 +331,8 @@ linker_file_register_modules(linker_file
        KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
            " in %s\n", lf->filename));
 
+       sx_assert(&kld_sx, SA_XLOCKED);
+
        if (linker_file_lookup_set(lf, "modmetadata_set", &start,
            &stop, NULL) != 0) {
                /*
@@ -403,10 +421,8 @@ linker_load_file(const char *filename, l
                                return (error);
                        }
                        modules = !TAILQ_EMPTY(&lf->modules);
-                       sx_xunlock(&kld_sx);
                        linker_file_register_sysctls(lf);
                        linker_file_sysinit(lf);
-                       sx_xlock(&kld_sx);
                        lf->flags |= LINKER_FILE_LINKED;
 
                        /*
@@ -657,10 +673,8 @@ linker_file_unload(linker_file_t file, i
         */
        if (file->flags & LINKER_FILE_LINKED) {
                file->flags &= ~LINKER_FILE_LINKED;
-               sx_xunlock(&kld_sx);
                linker_file_sysuninit(file);
                linker_file_unregister_sysctls(file);
-               sx_xlock(&kld_sx);
        }
        TAILQ_REMOVE(&linker_files, file, link);
 
@@ -729,15 +743,9 @@ int
 linker_file_lookup_set(linker_file_t file, const char *name,
     void *firstp, void *lastp, int *countp)
 {
-       int error, locked;
 
-       locked = sx_xlocked(&kld_sx);
-       if (!locked)
-               sx_xlock(&kld_sx);
-       error = LINKER_LOOKUP_SET(file, name, firstp, lastp, countp);
-       if (!locked)
-               sx_xunlock(&kld_sx);
-       return (error);
+       sx_assert(&kld_sx, SA_LOCKED);
+       return (LINKER_LOOKUP_SET(file, name, firstp, lastp, countp));
 }
 
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to