History

modules: remove modlist_lock

Now we always use stop_machine for module insertion or deletion, we no longer need the modlist_lock: merely disabling preemption is sufficient to block against list manipulation. This avoids deadlock on OOPSen where we can potentially grab the lock twice.

Rusty Russell committed 19 years ago

Commit 24da1cb1 parent 6c675bd1 file · +15 −21Browse files

Showing the changes to kernel/module.c (1 of 1 file). Show all

Unified · Split

kernel/module.c+15−21
@@ -61,10 +61,8 @@ extern int module_sysfs_initialized; · 60 unmodified lines
6161 /* If this is set, the section belongs in the init part of the module */
6262 #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
6363
64−/* Protects module list */
65−static DEFINE_SPINLOCK(modlist_lock);
66−
67−/* List of modules, protected by module_mutex AND modlist_lock */
64+/* List of modules, protected by module_mutex or preempt_disable
65+ * (add/delete uses stop_machine). */
6866 static DEFINE_MUTEX(module_mutex);
6967 static LIST_HEAD(modules);
7068
@@ -760,14 +758,13 @@ static void print_unload_info(struct seq_file *m, struct module *mod) · 689 unmodified lines
760758 void __symbol_put(const char *symbol)
761759 {
762760 struct module *owner;
763− unsigned long flags;
764761 const unsigned long *crc;
765762
766− spin_lock_irqsave(&modlist_lock, flags);
763+ preempt_disable();
767764 if (!__find_symbol(symbol, &owner, &crc, 1))
768765 BUG();
769766 module_put(owner);
770− spin_unlock_irqrestore(&modlist_lock, flags);
767+ preempt_enable();
771768 }
772769 EXPORT_SYMBOL(__symbol_put);
773770
@@ -1228,14 +1225,14 @@ static void free_module(struct module *mod) · 454 unmodified lines
12281225 void *__symbol_get(const char *symbol)
12291226 {
12301227 struct module *owner;
1231− unsigned long value, flags;
1228+ unsigned long value;
12321229 const unsigned long *crc;
12331230
1234− spin_lock_irqsave(&modlist_lock, flags);
1231+ preempt_disable();
12351232 value = __find_symbol(symbol, &owner, &crc, 1);
12361233 if (value && !strong_try_module_get(owner))
12371234 value = 0;
1238− spin_unlock_irqrestore(&modlist_lock, flags);
1235+ preempt_enable();
12391236
12401237 return (void *)value;
12411238 }
@@ -2308,11 +2305,10 @@ const struct seq_operations modules_op = { · 1066 unmodified lines
23082305 /* Given an address, look for it in the module exception tables. */
23092306 const struct exception_table_entry *search_module_extables(unsigned long addr)
23102307 {
2311− unsigned long flags;
23122308 const struct exception_table_entry *e = NULL;
23132309 struct module *mod;
23142310
2315− spin_lock_irqsave(&modlist_lock, flags);
2311+ preempt_disable();
23162312 list_for_each_entry(mod, &modules, list) {
23172313 if (mod->num_exentries == 0)
23182314 continue;
@@ -2323,7 +2319,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) · 4 unmodified lines
23232319 if (e)
23242320 break;
23252321 }
2326− spin_unlock_irqrestore(&modlist_lock, flags);
2322+ preempt_enable();
23272323
23282324 /* Now, if we found one, we are running inside it now, hence
23292325 we cannot unload the module, hence no refcnt needed. */
@@ -2335,25 +2331,24 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) · 5 unmodified lines
23352331 */
23362332 int is_module_address(unsigned long addr)
23372333 {
2338− unsigned long flags;
23392334 struct module *mod;
23402335
2341− spin_lock_irqsave(&modlist_lock, flags);
2336+ preempt_disable();
23422337
23432338 list_for_each_entry(mod, &modules, list) {
23442339 if (within(addr, mod->module_core, mod->core_size)) {
2345− spin_unlock_irqrestore(&modlist_lock, flags);
2340+ preempt_enable();
23462341 return 1;
23472342 }
23482343 }
23492344
2350− spin_unlock_irqrestore(&modlist_lock, flags);
2345+ preempt_enable();
23512346
23522347 return 0;
23532348 }
23542349
23552350
2356−/* Is this a valid kernel address? We don't grab the lock: we are oopsing. */
2351+/* Is this a valid kernel address? */
23572352 struct module *__module_text_address(unsigned long addr)
23582353 {
23592354 struct module *mod;
@@ -2368,11 +2363,10 @@ struct module *__module_text_address(unsigned long addr) · 8 unmodified lines
23682363 struct module *module_text_address(unsigned long addr)
23692364 {
23702365 struct module *mod;
2371− unsigned long flags;
23722366
2373− spin_lock_irqsave(&modlist_lock, flags);
2367+ preempt_disable();
23742368 mod = __module_text_address(addr);
2375− spin_unlock_irqrestore(&modlist_lock, flags);
2369+ preempt_enable();
23762370
23772371 return mod;
23782372 }