module_register_init fails, but driver is still loaded?

John Baldwin jhb at freebsd.org
Tue Aug 23 11:56:28 UTC 2011


On Thursday, August 04, 2011 12:23:15 pm Garrett Cooper wrote:
> Hi hackers,
>     I noticed that if anything fails while initializing a driver, the
> driver stays attached to the kernel as a module instead of being
> kicked when all references to the driver go to 0. Is this desired
> behavior (it doesn't seem like it, but I can see potential pros and
> cons of kicking the driver out of the kernel immediately when a
> failure state occurs)? I've seen this on 7.2 ~ 9-CURRENT. Example
> sourcecode and invocation attached below.

This is sort of a feature actually.  Consider the hard cases avg@ mentioned 
such as a kld that contains multiple modules.  What one could possibly do is
notice that all modules failed MOD_LOAD and do an unload in that case.  This
untested patch tries to do that:

Index: kern_linker.c
===================================================================
--- kern_linker.c	(revision 225077)
+++ kern_linker.c	(working copy)
@@ -378,7 +378,7 @@ linker_load_file(const char *filename, linker_file
 {
 	linker_class_t lc;
 	linker_file_t lf;
-	int foundfile, error;
+	int foundfile, error, modules;
 
 	/* Refuse to load modules if securelevel raised */
 	if (prison0.pr_securelevel > 0)
@@ -417,11 +417,22 @@ linker_load_file(const char *filename, linker_file
 				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
 				return (error);
 			}
+			modules = !TAILQ_EMPTY(&lf->modules);
 			KLD_UNLOCK();
 			linker_file_register_sysctls(lf);
 			linker_file_sysinit(lf);
 			KLD_LOCK();
 			lf->flags |= LINKER_FILE_LINKED;
+
+			/*
+			 * If all of the modules in this file failed
+			 * to load, unload the file and return an
+			 * error of ENOEXEC.
+			 */
+			if (modules && TAILQ_EMPTY(&lf->modules)) {
+				linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+				return (ENOEXEC);
+			}
 			*result = lf;
 			return (0);
 		}
@@ -625,7 +636,7 @@ linker_file_unload(linker_file_t file, int flags)
 
 	/*
 	 * Inform any modules associated with this file that they are
-	 * being be unloaded.
+	 * being unloaded.
 	 */
 	MOD_XLOCK;
 	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {


-- 
John Baldwin


More information about the freebsd-hackers mailing list