summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_linker.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-12-05 13:40:25 +0000
committerjhb <jhb@FreeBSD.org>2008-12-05 13:40:25 +0000
commit0ac14961cc48c1ab4910a0dfb21d6d4a3137f5a6 (patch)
treea8522c6b0e4d16f7f55489f7822e5cbf7405ddf4 /sys/kern/kern_linker.c
parentd57e5b9d8b3abb250cd15d2e7d49be4668ad956a (diff)
downloadFreeBSD-src-0ac14961cc48c1ab4910a0dfb21d6d4a3137f5a6.zip
FreeBSD-src-0ac14961cc48c1ab4910a0dfb21d6d4a3137f5a6.tar.gz
- 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
Diffstat (limited to 'sys/kern/kern_linker.c')
-rw-r--r--sys/kern/kern_linker.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index e232cdc..f657efa 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -587,7 +587,30 @@ linker_file_unload(linker_file_t file, int flags)
" 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, int flags)
/*
* 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;
OpenPOWER on IntegriCloud