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-head
mailing list