Module init reentry fix
PATCH 1/1 Module init reentry fix
Linus, please apply.
In some configurations, parport and bttv request a module inside their module_init function. Drop the lock around mod->init(), change module->live to module->state so we can detect modules which are in init.
Survives stress_modules.sh here for a few hours, and according to Kees, does fix the problem.
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
Name: Module init reentry fix
Author: Rusty Russell
Status: Tested on 2.5.51
D: This changes the code to drop the module_mutex() before calling the
D: module's init function, so module init functions can call
D: request_module(). This was trivial before someone broke the module
D: code to start non-live. Now it requires us to keep info on the
D: exact module state.
include/linux/module.h +19 -5
@@ -116,10 +116,16 @@ struct module_refatomic_t count; }____cacheline_aligned ; +enum module_state +{ +MODULE_STATE_LIVE , +MODULE_STATE_COMING , +MODULE_STATE_GOING , +}; +struct module { -/* Am I live (yet)? */ -int live; +enum module_state state;/* Member of list of modules */ struct list_head list;
@@ -177,6 +183,14 @@ struct modulechar args[0 ]; }; +/* FIXME: It'd be nice to isolate modules during init, too, so they +aren't used before they (may) fail. But presently too much code +(IDE & SCSI) require entry into the module during init.*/ +static inline int module_is_live (struct module *mod) +{ +return mod->state !=MODULE_STATE_GOING ; +} +#ifdef CONFIG_MODULE_UNLOAD void __symbol_put (const char *symbol);
@@ -195,7 +209,7 @@ static inline int try_module_get(structif (module) {unsigned int cpu =get_cpu (); -if (likely (module->live)) +if (likely (module_is_live (module)))local_inc (&module->ref[cpu].count);else ret =0 ;
@@ -210,7 +224,7 @@ static inline void module_put(struct modunsigned int cpu =get_cpu ();local_dec (&module->ref[cpu].count);/* Maybe they're waiting for us to drop reference? */ -if (unlikely (!module->live)) +if (unlikely (!module_is_live (module)))wake_up_process (module->waiter);put_cpu (); }
@@ -219,7 +233,7 @@ static inline void module_put(struct mod#else /*!CONFIG_MODULE_UNLOAD*/ static inline int try_module_get (struct module *module) { -return !module || module->live; +return !module ||module_is_live (module); }static inline void module_put (struct module *module) {
kernel/module.c +36 -33
139 lines not on this page · raw message