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

Unified · Split

kernel/module.c+15−21
@@ -61,10 +61,8 @@ extern int module_sysfs_initialized; · 60 unmodified lines
61/* If this is set, the section belongs in the init part of the module */61/* If this is set, the section belongs in the init part of the module */
62#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))62#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1))
63 63
64/* Protects module list */64/* List of modules, protected by module_mutex or preempt_disable
65static DEFINE_SPINLOCK(modlist_lock);65 * (add/delete uses stop_machine). */
66
67/* List of modules, protected by module_mutex AND modlist_lock */
68static DEFINE_MUTEX(module_mutex);66static DEFINE_MUTEX(module_mutex);
69static LIST_HEAD(modules);67static LIST_HEAD(modules);
70 68
@@ -760,14 +758,13 @@ static void print_unload_info(struct seq_file *m, struct module *mod) · 689 unmodified lines
760void __symbol_put(const char *symbol)758void __symbol_put(const char *symbol)
761{759{
762 struct module *owner;760 struct module *owner;
763 unsigned long flags;
764 const unsigned long *crc;761 const unsigned long *crc;
765 762
766 spin_lock_irqsave(&modlist_lock, flags);763 preempt_disable();
767 if (!__find_symbol(symbol, &owner, &crc, 1))764 if (!__find_symbol(symbol, &owner, &crc, 1))
768 BUG();765 BUG();
769 module_put(owner);766 module_put(owner);
770 spin_unlock_irqrestore(&modlist_lock, flags);767 preempt_enable();
771}768}
772EXPORT_SYMBOL(__symbol_put);769EXPORT_SYMBOL(__symbol_put);
773 770
@@ -1228,14 +1225,14 @@ static void free_module(struct module *mod) · 454 unmodified lines
1228void *__symbol_get(const char *symbol)1225void *__symbol_get(const char *symbol)
1229{1226{
1230 struct module *owner;1227 struct module *owner;
1231 unsigned long value, flags;1228 unsigned long value;
1232 const unsigned long *crc;1229 const unsigned long *crc;
1233 1230
1234 spin_lock_irqsave(&modlist_lock, flags);1231 preempt_disable();
1235 value = __find_symbol(symbol, &owner, &crc, 1);1232 value = __find_symbol(symbol, &owner, &crc, 1);
1236 if (value && !strong_try_module_get(owner))1233 if (value && !strong_try_module_get(owner))
1237 value = 0;1234 value = 0;
1238 spin_unlock_irqrestore(&modlist_lock, flags);1235 preempt_enable();
1239 1236
1240 return (void *)value;1237 return (void *)value;
1241}1238}
@@ -2308,11 +2305,10 @@ const struct seq_operations modules_op = { · 1066 unmodified lines
2308/* Given an address, look for it in the module exception tables. */2305/* Given an address, look for it in the module exception tables. */
2309const struct exception_table_entry *search_module_extables(unsigned long addr)2306const struct exception_table_entry *search_module_extables(unsigned long addr)
2310{2307{
2311 unsigned long flags;
2312 const struct exception_table_entry *e = NULL;2308 const struct exception_table_entry *e = NULL;
2313 struct module *mod;2309 struct module *mod;
2314 2310
2315 spin_lock_irqsave(&modlist_lock, flags);2311 preempt_disable();
2316 list_for_each_entry(mod, &modules, list) {2312 list_for_each_entry(mod, &modules, list) {
2317 if (mod->num_exentries == 0)2313 if (mod->num_exentries == 0)
2318 continue;2314 continue;
@@ -2323,7 +2319,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) · 4 unmodified lines
2323 if (e)2319 if (e)
2324 break;2320 break;
2325 }2321 }
2326 spin_unlock_irqrestore(&modlist_lock, flags);2322 preempt_enable();
2327 2323
2328 /* Now, if we found one, we are running inside it now, hence2324 /* Now, if we found one, we are running inside it now, hence
2329 we cannot unload the module, hence no refcnt needed. */2325 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
2335 */2331 */
2336int is_module_address(unsigned long addr)2332int is_module_address(unsigned long addr)
2337{2333{
2338 unsigned long flags;
2339 struct module *mod;2334 struct module *mod;
2340 2335
2341 spin_lock_irqsave(&modlist_lock, flags);2336 preempt_disable();
2342 2337
2343 list_for_each_entry(mod, &modules, list) {2338 list_for_each_entry(mod, &modules, list) {
2344 if (within(addr, mod->module_core, mod->core_size)) {2339 if (within(addr, mod->module_core, mod->core_size)) {
2345 spin_unlock_irqrestore(&modlist_lock, flags);2340 preempt_enable();
2346 return 1;2341 return 1;
2347 }2342 }
2348 }2343 }
2349 2344
2350 spin_unlock_irqrestore(&modlist_lock, flags);2345 preempt_enable();
2351 2346
2352 return 0;2347 return 0;
2353}2348}
2354 2349
2355 2350
2356/* Is this a valid kernel address? We don't grab the lock: we are oopsing. */2351/* Is this a valid kernel address? */
2357struct module *__module_text_address(unsigned long addr)2352struct module *__module_text_address(unsigned long addr)
2358{2353{
2359 struct module *mod;2354 struct module *mod;
@@ -2368,11 +2363,10 @@ struct module *__module_text_address(unsigned long addr) · 8 unmodified lines
2368struct module *module_text_address(unsigned long addr)2363struct module *module_text_address(unsigned long addr)
2369{2364{
2370 struct module *mod;2365 struct module *mod;
2371 unsigned long flags;
2372 2366
2373 spin_lock_irqsave(&modlist_lock, flags);2367 preempt_disable();
2374 mod = __module_text_address(addr);2368 mod = __module_text_address(addr);
2375 spin_unlock_irqrestore(&modlist_lock, flags);2369 preempt_enable();
2376 2370
2377 return mod;2371 return mod;
2378}2372}