Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys 1. Add an allocator for 'struct module *' and use it ins...



details:   https://anonhg.NetBSD.org/src/rev/6eb4bb4de1d0
branches:  trunk
changeset: 755874:6eb4bb4de1d0
user:      pgoyette <pgoyette%NetBSD.org@localhost>
date:      Sat Jun 26 07:23:57 2010 +0000

description:
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 njoly@.

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.

diffstat:

 sys/kern/init_main.c   |  10 +++--
 sys/kern/kern_module.c |  90 ++++++++++++++++++++++++++++++++++++++-----------
 sys/sys/module.h       |   8 +++-
 3 files changed, 82 insertions(+), 26 deletions(-)

diffs (296 lines):

diff -r 1401b34de959 -r 6eb4bb4de1d0 sys/kern/init_main.c
--- a/sys/kern/init_main.c      Sat Jun 26 06:43:13 2010 +0000
+++ b/sys/kern/init_main.c      Sat Jun 26 07:23:57 2010 +0000
@@ -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
diff -r 1401b34de959 -r 6eb4bb4de1d0 sys/kern/kern_module.c
--- a/sys/kern/kern_module.c    Sat Jun 26 06:43:13 2010 +0000
+++ b/sys/kern/kern_module.c    Sat Jun 26 07:23:57 2010 +0000
@@ -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);
diff -r 1401b34de959 -r 6eb4bb4de1d0 sys/sys/module.h
--- a/sys/sys/module.h  Sat Jun 26 06:43:13 2010 +0000
+++ b/sys/sys/module.h  Sat Jun 26 07:23:57 2010 +0000
@@ -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);



Home | Main Index | Thread Index | Old Index