Author: markj
Date: Thu Dec 19 03:48:36 2013
New Revision: 259587
URL: http://svnweb.freebsd.org/changeset/base/259587

Log:
  Invoke the kld_* event handlers from linker_load_file() and
  linker_unload_file() rather than kern_kldload() and kern_kldunload(). This
  ensures that the handlers are invoked for files that are loaded/unloaded
  automatically as dependencies. Previously, they were only invoked for files
  loaded by a user.
  
  As a side effect, the kld_load and kld_unload handlers are now invoked with
  the kernel linker lock exclusively held.
  
  Reported by:  avg
  Reviewed by:  jhb
  MFC after:    2 weeks

Modified:
  head/sys/kern/kern_linker.c

Modified: head/sys/kern/kern_linker.c
==============================================================================
--- head/sys/kern/kern_linker.c Thu Dec 19 03:21:53 2013        (r259586)
+++ head/sys/kern/kern_linker.c Thu Dec 19 03:48:36 2013        (r259587)
@@ -434,6 +434,7 @@ linker_load_file(const char *filename, l
                                linker_file_unload(lf, LINKER_UNLOAD_FORCE);
                                return (ENOEXEC);
                        }
+                       EVENTHANDLER_INVOKE(kld_load, lf);
                        *result = lf;
                        return (0);
                }
@@ -609,6 +610,12 @@ linker_file_unload(linker_file_t file, i
                return (0);
        }
 
+       /* Give eventhandlers a chance to prevent the unload. */
+       error = 0;
+       EVENTHANDLER_INVOKE(kld_unload_try, file, &error);
+       if (error != 0)
+               return (EBUSY);
+
        KLD_DPF(FILE, ("linker_file_unload: file is unloading,"
            " informing modules\n"));
 
@@ -690,6 +697,10 @@ linker_file_unload(linker_file_t file, i
        }
 
        LINKER_UNLOAD(file);
+
+       EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
+           file->size);
+
        if (file->filename) {
                free(file->filename, M_LINKER);
                file->filename = NULL;
@@ -1033,10 +1044,7 @@ kern_kldload(struct thread *td, const ch
        lf->userrefs++;
        if (fileid != NULL)
                *fileid = lf->id;
-
-       sx_downgrade(&kld_sx);
-       EVENTHANDLER_INVOKE(kld_load, lf);
-       sx_sunlock(&kld_sx);
+       sx_xunlock(&kld_sx);
 
 done:
        CURVNET_RESTORE();
@@ -1066,9 +1074,6 @@ int
 kern_kldunload(struct thread *td, int fileid, int flags)
 {
        linker_file_t lf;
-       char *filename = NULL;
-       caddr_t address;
-       size_t size;
        int error = 0;
 
        if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
@@ -1083,10 +1088,7 @@ kern_kldunload(struct thread *td, int fi
        if (lf) {
                KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
 
-               EVENTHANDLER_INVOKE(kld_unload_try, lf, &error);
-               if (error != 0)
-                       error = EBUSY;
-               else if (lf->userrefs == 0) {
+               if (lf->userrefs == 0) {
                        /*
                         * XXX: maybe LINKER_UNLOAD_FORCE should override ?
                         */
@@ -1094,11 +1096,6 @@ kern_kldunload(struct thread *td, int fi
                            " loaded by the kernel\n");
                        error = EBUSY;
                } else {
-                       /* Save data needed for the kld_unload callbacks. */
-                       filename = strdup(lf->filename, M_TEMP);
-                       address = lf->address;
-                       size = lf->size;
-
                        lf->userrefs--;
                        error = linker_file_unload(lf, flags);
                        if (error)
@@ -1106,14 +1103,7 @@ kern_kldunload(struct thread *td, int fi
                }
        } else
                error = ENOENT;
-
-       if (error == 0) {
-               sx_downgrade(&kld_sx);
-               EVENTHANDLER_INVOKE(kld_unload, filename, address, size);
-               sx_sunlock(&kld_sx);
-       } else
-               sx_xunlock(&kld_sx);
-       free(filename, M_TEMP);
+       sx_xunlock(&kld_sx);
 
        CURVNET_RESTORE();
        return (error);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to