svn commit: r185635 - in head/sys: kern sys

John Baldwin jhb at FreeBSD.org
Fri Dec 5 05:40:25 PST 2008


Author: jhb
Date: Fri Dec  5 13:40:25 2008
New Revision: 185635
URL: http://svn.freebsd.org/changeset/base/185635

Log:
  - Invoke MOD_QUIESCE on all modules in a linker file (kld) before
    unloading any modules.  As a result, if any module veto's an unload
    request via MOD_QUIESCE, the entire set of modules for that linker
    file will remain loaded and active now rather than leaving the kld
    in a weird state where some modules are loaded and some are unloaded.
  - This also moves the logic for handling the "forced" unload flag out of
    kern_module.c and into kern_linker.c which is a bit cleaner.
  - Add a module_name() routine that returns the name of a module and use that
    instead of printing pointer values in debug messages when a module fails
    MOD_QUIESCE or MOD_UNLOAD.
  
  MFC after:	1 month

Modified:
  head/sys/kern/kern_linker.c
  head/sys/kern/kern_module.c
  head/sys/sys/module.h

Modified: head/sys/kern/kern_linker.c
==============================================================================
--- head/sys/kern/kern_linker.c	Fri Dec  5 11:34:36 2008	(r185634)
+++ head/sys/kern/kern_linker.c	Fri Dec  5 13:40:25 2008	(r185635)
@@ -587,7 +587,30 @@ linker_file_unload(linker_file_t file, i
 	    " informing modules\n"));
 
 	/*
-	 * Inform any modules associated with this file.
+	 * Quiesce all the modules to give them a chance to veto the unload.
+	 */
+	MOD_SLOCK;
+	for (mod = TAILQ_FIRST(&file->modules); mod;
+	     mod = module_getfnext(mod)) {
+
+		error = module_quiesce(mod);
+		if (error != 0 && flags != LINKER_UNLOAD_FORCE) {
+			KLD_DPF(FILE, ("linker_file_unload: module %s"
+			    " vetoed unload\n", module_getname(mod)));
+			/*
+			 * XXX: Do we need to tell all the quiesced modules
+			 * that they can resume work now via a new module
+			 * event?
+			 */
+			MOD_SUNLOCK;
+			return (error);
+		}
+	}
+	MOD_SUNLOCK;
+
+	/*
+	 * Inform any modules associated with this file that they are
+	 * being be unloaded.
 	 */
 	MOD_XLOCK;
 	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
@@ -597,9 +620,9 @@ linker_file_unload(linker_file_t file, i
 		/*
 		 * Give the module a chance to veto the unload.
 		 */
-		if ((error = module_unload(mod, flags)) != 0) {
-			KLD_DPF(FILE, ("linker_file_unload: module %p"
-			    " vetoes unload\n", mod));
+		if ((error = module_unload(mod)) != 0) {
+			KLD_DPF(FILE, ("linker_file_unload: module %s"
+			    " failed unload\n", mod));
 			return (error);
 		}
 		MOD_XLOCK;

Modified: head/sys/kern/kern_module.c
==============================================================================
--- head/sys/kern/kern_module.c	Fri Dec  5 11:34:36 2008	(r185634)
+++ head/sys/kern/kern_module.c	Fri Dec  5 13:40:25 2008	(r185635)
@@ -196,9 +196,7 @@ module_release(module_t mod)
 		TAILQ_REMOVE(&modules, mod, link);
 		if (mod->file)
 			TAILQ_REMOVE(&mod->file->modules, mod, flink);
-		MOD_XUNLOCK;
 		free(mod, M_MODULE);
-		MOD_XLOCK;
 	}
 }
 
@@ -232,16 +230,25 @@ module_lookupbyid(int modid)
 }
 
 int
-module_unload(module_t mod, int flags)
+module_quiesce(module_t mod)
 {
 	int error;
 
 	mtx_lock(&Giant);
 	error = MOD_EVENT(mod, MOD_QUIESCE);
+	mtx_unlock(&Giant);
 	if (error == EOPNOTSUPP || error == EINVAL)
 		error = 0;
-	if (error == 0 || flags == LINKER_UNLOAD_FORCE)
-		error = MOD_EVENT(mod, MOD_UNLOAD);
+	return (error);
+}
+
+int
+module_unload(module_t mod)
+{
+	int error;
+
+	mtx_lock(&Giant);
+	error = MOD_EVENT(mod, MOD_UNLOAD);
 	mtx_unlock(&Giant);
 	return (error);
 }
@@ -262,6 +269,14 @@ module_getfnext(module_t mod)
 	return (TAILQ_NEXT(mod, flink));
 }
 
+const char *
+module_getname(module_t mod)
+{
+
+	MOD_LOCK_ASSERT;
+	return (mod->name);
+}
+
 void
 module_setspecific(module_t mod, modspecific_t *datap)
 {

Modified: head/sys/sys/module.h
==============================================================================
--- head/sys/sys/module.h	Fri Dec  5 11:34:36 2008	(r185634)
+++ head/sys/sys/module.h	Fri Dec  5 13:40:25 2008	(r185635)
@@ -154,11 +154,13 @@ void	module_register_init(const void *);
 int	module_register(const struct moduledata *, struct linker_file *);
 module_t	module_lookupbyname(const char *);
 module_t	module_lookupbyid(int);
+int	module_quiesce(module_t);
 void	module_reference(module_t);
 void	module_release(module_t);
-int	module_unload(module_t, int flags);
+int	module_unload(module_t);
 int	module_getid(module_t);
 module_t	module_getfnext(module_t);
+const char *	module_getname(module_t);
 void	module_setspecific(module_t, modspecific_t *);
 struct linker_file *module_file(module_t);
 


More information about the svn-src-all mailing list