Module Name:    src
Committed By:   pgoyette
Date:           Sat Jun 26 07:23:57 UTC 2010

Modified Files:
        src/sys/kern: init_main.c kern_module.c
        src/sys/sys: module.h

Log Message:
1. Add an allocator for 'struct module *' and use it instead of local
   allocations.

2. Add a new member mod_flags to the 'struct module *' and define
   MODFLG_MUST_FORCE.  If this flag is set and the entry is on the list
   of builtins, it means that the module has been explicitly unloaded
   and any re-loads will require the MODCTL_LOAD_FORCE flag. Provide a
   module_require_force() method to set this flag;  once set, it should
   never be unset.

3. Rename original module_init2() to module_start_unload_thread() to be
   more descriptive of what it does.

4. Add a new module_builtin_require_force() routine that sets the
   MODFLG_MUST_FORCE flag for any module that has not yet successfully
   been initialized.  Call it after module_init_class(MODULE_CLASS_ANY)
   to disable remaining built-in modules.

This makes built-in versions of the xxxVERBOSE modules work once more,
resolving breakage reported by jruoho@ and nj...@.

Discussed on tech-kern, and comments and suggestions implemented.  No
additional discussion for last week.  Tested only on amd64 systems, but
there's nothing here that should be port- or architecture-specific (no
more specific than existing module implementation) so others should not
break.


To generate a diff of this commit:
cvs rdiff -u -r1.421 -r1.422 src/sys/kern/init_main.c
cvs rdiff -u -r1.69 -r1.70 src/sys/kern/kern_module.c
cvs rdiff -u -r1.23 -r1.24 src/sys/sys/module.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/init_main.c
diff -u src/sys/kern/init_main.c:1.421 src/sys/kern/init_main.c:1.422
--- src/sys/kern/init_main.c:1.421	Fri Jun 25 15:10:42 2010
+++ src/sys/kern/init_main.c	Sat Jun 26 07:23:57 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: init_main.c,v 1.421 2010/06/25 15:10:42 tsutsui Exp $	*/
+/*	$NetBSD: init_main.c,v 1.422 2010/06/26 07:23:57 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.421 2010/06/25 15:10:42 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.422 2010/06/26 07:23:57 pgoyette Exp $");
 
 #include "opt_ddb.h"
 #include "opt_ipsec.h"
@@ -431,7 +431,7 @@
 	loginit();
 
 	/* Second part of module system initialization. */
-	module_init2();
+	module_start_unload_thread();
 
 	/* Initialize the file systems. */
 #ifdef NVNODE_IMPLICIT
@@ -595,9 +595,11 @@
 
 	/*
 	 * Load any remaining builtin modules, and hand back temporary
-	 * storage to the VM system.
+	 * storage to the VM system.  Then require force when loading any
+	 * remaining un-init'ed built-in modules to avoid later surprises.
 	 */
 	module_init_class(MODULE_CLASS_ANY);
+	module_builtin_require_force();
 
 	/*
 	 * Finalize configuration now that all real devices have been

Index: src/sys/kern/kern_module.c
diff -u src/sys/kern/kern_module.c:1.69 src/sys/kern/kern_module.c:1.70
--- src/sys/kern/kern_module.c:1.69	Wed May 26 23:53:21 2010
+++ src/sys/kern/kern_module.c	Sat Jun 26 07:23:57 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_module.c,v 1.69 2010/05/26 23:53:21 pooka Exp $	*/
+/*	$NetBSD: kern_module.c,v 1.70 2010/06/26 07:23:57 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.69 2010/05/26 23:53:21 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.70 2010/06/26 07:23:57 pgoyette Exp $");
 
 #define _MODULE_INTERNAL
 
@@ -87,9 +87,11 @@
 static modinfo_t module_dummy;
 __link_set_add_rodata(modules, module_dummy);
 
+static module_t	*module_newmodule(modsrc_t);
+static void	module_require_force(module_t *);
 static int	module_do_load(const char *, bool, int, prop_dictionary_t,
 		    module_t **, modclass_t class, bool);
-static int	module_do_unload(const char *);
+static int	module_do_unload(const char *, bool);
 static int	module_do_builtin(const char *, module_t **);
 static int	module_fetch_info(module_t *);
 static void	module_thread(void *);
@@ -155,6 +157,32 @@
 }
 
 /*
+ * Allocate a new module_t
+ */
+static module_t *
+module_newmodule(modsrc_t source)
+{
+	module_t *mod;
+
+	mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
+	if (mod != NULL) {
+		mod->mod_source = source;
+		mod->mod_info = NULL;
+		mod->mod_flags = 0;
+	}
+	return mod;
+}
+
+/*
+ * Require the -f (force) flag to load a module
+ */
+static void
+module_require_force(struct module *mod)
+{
+	mod->mod_flags |= MODFLG_MUST_FORCE;
+}
+
+/*
  * Add modules to the builtin list.  This can done at boottime or
  * at runtime if the module is linked into the kernel with an
  * external linker.  All or none of the input will be handled.
@@ -192,9 +220,8 @@
 			mipskip++;
 			continue;
 		}
-		modp[i] = kmem_zalloc(sizeof(*modp[i]), KM_SLEEP);
+		modp[i] = module_newmodule(MODULE_SOURCE_KERNEL);
 		modp[i]->mod_info = mip[i+mipskip];
-		modp[i]->mod_source = MODULE_SOURCE_KERNEL;
 	}
 	mutex_enter(&module_lock);
 
@@ -265,7 +292,7 @@
 			return rv;
 
 		mutex_enter(&module_lock);
-		rv = module_do_unload(mi->mi_name);
+		rv = module_do_unload(mi->mi_name, true);
 		if (rv) {
 			goto out;
 		}
@@ -335,12 +362,12 @@
 }
 
 /*
- * module_init2:
+ * module_start_unload_thread:
  *
  *	Start the auto unload kthread.
  */
 void
-module_init2(void)
+module_start_unload_thread(void)
 {
 	int error;
 
@@ -350,6 +377,24 @@
 		panic("module_init: %d", error);
 }
 
+/*
+ * module_builtin_require_force
+ *
+ * Require MODCTL_MUST_FORCE to load any built-in modules that have 
+ * not yet been initialized
+ */
+void
+module_builtin_require_force(void)
+{
+	module_t *mod;
+
+	mutex_enter(&module_lock);
+	TAILQ_FOREACH(mod, &module_builtins, mod_chain) {
+		module_require_force(mod);
+	}
+	mutex_exit(&module_lock);
+}
+
 static struct sysctllog *module_sysctllog;
 
 static void
@@ -412,10 +457,14 @@
 			/*
 			 * If initializing a builtin module fails, don't try
 			 * to load it again.  But keep it around and queue it
-			 * on the disabled list after we're done with module
-			 * init.
+			 * on the builtins list after we're done with module
+			 * init.  Don't set it to MODFLG_MUST_FORCE in case a
+			 * future attempt to initialize can be successful.
+			 * (If the module has previously been set to
+			 * MODFLG_MUST_FORCE, don't try to override that!)
 			 */
-			if (module_do_builtin(mi->mi_name, NULL) != 0) {
+			if (mod->mod_flags & MODFLG_MUST_FORCE ||
+			    module_do_builtin(mi->mi_name, NULL) != 0) {
 				TAILQ_REMOVE(&module_builtins, mod, mod_chain);
 				TAILQ_INSERT_TAIL(&bi_fail, mod, mod_chain);
 			}
@@ -438,7 +487,7 @@
 		}
 	} while (mod != NULL);
 
-	/* failed builtin modules remain disabled */
+	/* return failed builtin modules to builtin list */
 	while ((mod = TAILQ_FIRST(&bi_fail)) != NULL) {
 		TAILQ_REMOVE(&bi_fail, mod, mod_chain);
 		TAILQ_INSERT_TAIL(&module_builtins, mod, mod_chain);
@@ -544,7 +593,7 @@
 	}
 
 	mutex_enter(&module_lock);
-	error = module_do_unload(name);
+	error = module_do_unload(name, true);
 	mutex_exit(&module_lock);
 
 	return error;
@@ -794,7 +843,8 @@
 		}
 	}
 	if (mod) {
-		if ((flags & MODCTL_LOAD_FORCE) == 0) {
+		if ((mod->mod_flags & MODFLG_MUST_FORCE) &&
+		    (flags & MODCTL_LOAD_FORCE) == 0) {
 			if (!autoload) {
 				module_error("use -f to reinstate "
 				    "builtin module \"%s\"", name);
@@ -839,7 +889,7 @@
 				return 0;
 			}
 		}				
-		mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
+		mod = module_newmodule(MODULE_SOURCE_FILESYS);
 		if (mod == NULL) {
 			module_error("out of memory for `%s'", name);
 			depth--;
@@ -853,7 +903,6 @@
 			depth--;
 			return error;
 		}
-		mod->mod_source = MODULE_SOURCE_FILESYS;
 		TAILQ_INSERT_TAIL(&pending, mod, mod_chain);
 
 		error = module_fetch_info(mod);
@@ -1048,7 +1097,7 @@
  *	Helper routine: do the dirty work of unloading a module.
  */
 static int
-module_do_unload(const char *name)
+module_do_unload(const char *name, bool load_requires_force)
 {
 	module_t *mod;
 	int error;
@@ -1086,6 +1135,8 @@
 	}
 	if (mod->mod_source == MODULE_SOURCE_KERNEL) {
 		mod->mod_nrequired = 0; /* will be re-parsed */
+		if (load_requires_force)
+			module_require_force(mod);
 		TAILQ_INSERT_TAIL(&module_builtins, mod, mod_chain);
 		module_builtinlist++;
 	} else {
@@ -1108,11 +1159,10 @@
 	module_t *mod;
 	int error;
 
-	mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
+	mod = module_newmodule(MODULE_SOURCE_BOOT);
 	if (mod == NULL) {
 		return ENOMEM;
 	}
-	mod->mod_source = MODULE_SOURCE_BOOT;
 
 	error = kobj_load_mem(&mod->mod_kobj, base, size);
 	if (error != 0) {
@@ -1218,7 +1268,7 @@
 			mi = mod->mod_info;
 			error = (*mi->mi_modcmd)(MODULE_CMD_AUTOUNLOAD, NULL);
 			if (error == 0 || error == ENOTTY) {
-				(void)module_do_unload(mi->mi_name);
+				(void)module_do_unload(mi->mi_name, false);
 			}
 		}
 		mutex_exit(&module_lock);

Index: src/sys/sys/module.h
diff -u src/sys/sys/module.h:1.23 src/sys/sys/module.h:1.24
--- src/sys/sys/module.h:1.23	Mon May 24 03:50:25 2010
+++ src/sys/sys/module.h	Sat Jun 26 07:23:57 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: module.h,v 1.23 2010/05/24 03:50:25 pgoyette Exp $	*/
+/*	$NetBSD: module.h,v 1.24 2010/06/26 07:23:57 pgoyette Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -90,6 +90,9 @@
 	time_t			mod_autotime;
 	void 			*mod_ctf;
 	u_int			mod_fbtentries;	/* DTrace FBT entrie count */
+	int			mod_flags;
+#define MODFLG_MUST_FORCE	0x01
+
 } module_t;
 
 /*
@@ -120,7 +123,8 @@
 extern u_int		module_gen;
 
 void	module_init(void);
-void	module_init2(void);
+void	module_start_unload_thread(void);
+void	module_builtin_require_force(void);
 void	module_init_md(void);
 void	module_init_class(modclass_t);
 int	module_prime(void *, size_t);

Reply via email to