Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jan 2009 18:32:43 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r187553 - in stable/7/sys: . contrib/pf dev/cxgb kern sys
Message-ID:  <200901211832.n0LIWhig086513@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Wed Jan 21 18:32:43 2009
New Revision: 187553
URL: http://svn.freebsd.org/changeset/base/187553

Log:
  MFC: Invoke MOD_QUIESCE on all modules in a linker file (kld) before
  unloading any modules.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/kern/kern_linker.c
  stable/7/sys/kern/kern_module.c
  stable/7/sys/sys/module.h

Modified: stable/7/sys/kern/kern_linker.c
==============================================================================
--- stable/7/sys/kern/kern_linker.c	Wed Jan 21 18:26:10 2009	(r187552)
+++ stable/7/sys/kern/kern_linker.c	Wed Jan 21 18:32:43 2009	(r187553)
@@ -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: stable/7/sys/kern/kern_module.c
==============================================================================
--- stable/7/sys/kern/kern_module.c	Wed Jan 21 18:26:10 2009	(r187552)
+++ stable/7/sys/kern/kern_module.c	Wed Jan 21 18:32:43 2009	(r187553)
@@ -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: stable/7/sys/sys/module.h
==============================================================================
--- stable/7/sys/sys/module.h	Wed Jan 21 18:26:10 2009	(r187552)
+++ stable/7/sys/sys/module.h	Wed Jan 21 18:32:43 2009	(r187553)
@@ -141,11 +141,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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901211832.n0LIWhig086513>