Skip to contentSkip to conversation

Module init reentry fix

PATCH New Rusty Russell 1 participant 1 message Dec 13, 2002 Module support

lore
Share & tools
lore
#0 lore raw

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
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .27854-linux-2.5.51/include/linux/module.h .27854-linux-2.5.51.updated/include/linux/module.h
@@ -116,10 +116,16 @@ struct module_ref
 	atomic_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 module
 	char 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(struct 
 
 	if (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 mod
 		unsigned 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