diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2010-06-05 13:17:36 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-06-04 21:47:36 -0400 |
commit | 75676500f8298f0ee89db12db97294883c4b768e (patch) | |
tree | fbd74f1b6bfd258fac980c6cc3d4fa9eafa47d51 /kernel | |
parent | 6407ebb271fc34440b306f305e1efb7685eece26 (diff) |
module: make locking more fine-grained.
Kay Sievers <kay.sievers@vrfy.org> reports that we still have some
contention over module loading which is slowing boot.
Linus also disliked a previous "drop lock and regrab" patch to fix the
bne2 "gave up waiting for init of module libcrc32c" message.
This is more ambitious: we only grab the lock where we need it.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Brandon Philips <brandon@ifup.org>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/kernel/module.c b/kernel/module.c index 808aa18dd661..d293c213c22c 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -72,7 +72,11 @@ | |||
72 | /* If this is set, the section belongs in the init part of the module */ | 72 | /* If this is set, the section belongs in the init part of the module */ |
73 | #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) | 73 | #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) |
74 | 74 | ||
75 | /* List of modules, protected by module_mutex or preempt_disable | 75 | /* |
76 | * Mutex protects: | ||
77 | * 1) List of modules (also safely readable with preempt_disable), | ||
78 | * 2) module_use links, | ||
79 | * 3) module_addr_min/module_addr_max. | ||
76 | * (delete uses stop_machine/add uses RCU list operations). */ | 80 | * (delete uses stop_machine/add uses RCU list operations). */ |
77 | DEFINE_MUTEX(module_mutex); | 81 | DEFINE_MUTEX(module_mutex); |
78 | EXPORT_SYMBOL_GPL(module_mutex); | 82 | EXPORT_SYMBOL_GPL(module_mutex); |
@@ -90,7 +94,8 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq); | |||
90 | 94 | ||
91 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); | 95 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
92 | 96 | ||
93 | /* Bounds of module allocation, for speeding __module_address */ | 97 | /* Bounds of module allocation, for speeding __module_address. |
98 | * Protected by module_mutex. */ | ||
94 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; | 99 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; |
95 | 100 | ||
96 | int register_module_notifier(struct notifier_block * nb) | 101 | int register_module_notifier(struct notifier_block * nb) |
@@ -329,7 +334,7 @@ static bool find_symbol_in_section(const struct symsearch *syms, | |||
329 | } | 334 | } |
330 | 335 | ||
331 | /* Find a symbol and return it, along with, (optional) crc and | 336 | /* Find a symbol and return it, along with, (optional) crc and |
332 | * (optional) module which owns it */ | 337 | * (optional) module which owns it. Needs preempt disabled or module_mutex. */ |
333 | const struct kernel_symbol *find_symbol(const char *name, | 338 | const struct kernel_symbol *find_symbol(const char *name, |
334 | struct module **owner, | 339 | struct module **owner, |
335 | const unsigned long **crc, | 340 | const unsigned long **crc, |
@@ -576,7 +581,7 @@ static int add_module_usage(struct module *a, struct module *b) | |||
576 | return 0; | 581 | return 0; |
577 | } | 582 | } |
578 | 583 | ||
579 | /* Module a uses b */ | 584 | /* Module a uses b: caller needs module_mutex() */ |
580 | int use_module(struct module *a, struct module *b) | 585 | int use_module(struct module *a, struct module *b) |
581 | { | 586 | { |
582 | int err; | 587 | int err; |
@@ -610,6 +615,7 @@ static void module_unload_free(struct module *mod) | |||
610 | { | 615 | { |
611 | struct module_use *use, *tmp; | 616 | struct module_use *use, *tmp; |
612 | 617 | ||
618 | mutex_lock(&module_mutex); | ||
613 | list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) { | 619 | list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) { |
614 | struct module *i = use->target; | 620 | struct module *i = use->target; |
615 | DEBUGP("%s unusing %s\n", mod->name, i->name); | 621 | DEBUGP("%s unusing %s\n", mod->name, i->name); |
@@ -618,6 +624,7 @@ static void module_unload_free(struct module *mod) | |||
618 | list_del(&use->target_list); | 624 | list_del(&use->target_list); |
619 | kfree(use); | 625 | kfree(use); |
620 | } | 626 | } |
627 | mutex_unlock(&module_mutex); | ||
621 | } | 628 | } |
622 | 629 | ||
623 | #ifdef CONFIG_MODULE_FORCE_UNLOAD | 630 | #ifdef CONFIG_MODULE_FORCE_UNLOAD |
@@ -784,13 +791,14 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, | |||
784 | blocking_notifier_call_chain(&module_notify_list, | 791 | blocking_notifier_call_chain(&module_notify_list, |
785 | MODULE_STATE_GOING, mod); | 792 | MODULE_STATE_GOING, mod); |
786 | async_synchronize_full(); | 793 | async_synchronize_full(); |
787 | mutex_lock(&module_mutex); | 794 | |
788 | /* Store the name of the last unloaded module for diagnostic purposes */ | 795 | /* Store the name of the last unloaded module for diagnostic purposes */ |
789 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); | 796 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); |
790 | ddebug_remove_module(mod->name); | 797 | ddebug_remove_module(mod->name); |
791 | free_module(mod); | ||
792 | 798 | ||
793 | out: | 799 | free_module(mod); |
800 | return 0; | ||
801 | out: | ||
794 | mutex_unlock(&module_mutex); | 802 | mutex_unlock(&module_mutex); |
795 | return ret; | 803 | return ret; |
796 | } | 804 | } |
@@ -1006,6 +1014,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
1006 | { | 1014 | { |
1007 | const unsigned long *crc; | 1015 | const unsigned long *crc; |
1008 | 1016 | ||
1017 | /* Since this should be found in kernel (which can't be removed), | ||
1018 | * no locking is necessary. */ | ||
1009 | if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL, | 1019 | if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL, |
1010 | &crc, true, false)) | 1020 | &crc, true, false)) |
1011 | BUG(); | 1021 | BUG(); |
@@ -1048,8 +1058,7 @@ static inline int same_magic(const char *amagic, const char *bmagic, | |||
1048 | } | 1058 | } |
1049 | #endif /* CONFIG_MODVERSIONS */ | 1059 | #endif /* CONFIG_MODVERSIONS */ |
1050 | 1060 | ||
1051 | /* Resolve a symbol for this module. I.e. if we find one, record usage. | 1061 | /* Resolve a symbol for this module. I.e. if we find one, record usage. */ |
1052 | Must be holding module_mutex. */ | ||
1053 | static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, | 1062 | static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, |
1054 | unsigned int versindex, | 1063 | unsigned int versindex, |
1055 | const char *name, | 1064 | const char *name, |
@@ -1059,6 +1068,7 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, | |||
1059 | const struct kernel_symbol *sym; | 1068 | const struct kernel_symbol *sym; |
1060 | const unsigned long *crc; | 1069 | const unsigned long *crc; |
1061 | 1070 | ||
1071 | mutex_lock(&module_mutex); | ||
1062 | sym = find_symbol(name, &owner, &crc, | 1072 | sym = find_symbol(name, &owner, &crc, |
1063 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); | 1073 | !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); |
1064 | /* use_module can fail due to OOM, | 1074 | /* use_module can fail due to OOM, |
@@ -1068,6 +1078,7 @@ static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs, | |||
1068 | || !use_module(mod, owner)) | 1078 | || !use_module(mod, owner)) |
1069 | sym = NULL; | 1079 | sym = NULL; |
1070 | } | 1080 | } |
1081 | mutex_unlock(&module_mutex); | ||
1071 | return sym; | 1082 | return sym; |
1072 | } | 1083 | } |
1073 | 1084 | ||
@@ -1306,10 +1317,12 @@ static void add_usage_links(struct module *mod) | |||
1306 | struct module_use *use; | 1317 | struct module_use *use; |
1307 | int nowarn; | 1318 | int nowarn; |
1308 | 1319 | ||
1320 | mutex_lock(&module_mutex); | ||
1309 | list_for_each_entry(use, &mod->target_list, target_list) { | 1321 | list_for_each_entry(use, &mod->target_list, target_list) { |
1310 | nowarn = sysfs_create_link(use->target->holders_dir, | 1322 | nowarn = sysfs_create_link(use->target->holders_dir, |
1311 | &mod->mkobj.kobj, mod->name); | 1323 | &mod->mkobj.kobj, mod->name); |
1312 | } | 1324 | } |
1325 | mutex_unlock(&module_mutex); | ||
1313 | #endif | 1326 | #endif |
1314 | } | 1327 | } |
1315 | 1328 | ||
@@ -1318,8 +1331,10 @@ static void del_usage_links(struct module *mod) | |||
1318 | #ifdef CONFIG_MODULE_UNLOAD | 1331 | #ifdef CONFIG_MODULE_UNLOAD |
1319 | struct module_use *use; | 1332 | struct module_use *use; |
1320 | 1333 | ||
1334 | mutex_lock(&module_mutex); | ||
1321 | list_for_each_entry(use, &mod->target_list, target_list) | 1335 | list_for_each_entry(use, &mod->target_list, target_list) |
1322 | sysfs_remove_link(use->target->holders_dir, mod->name); | 1336 | sysfs_remove_link(use->target->holders_dir, mod->name); |
1337 | mutex_unlock(&module_mutex); | ||
1323 | #endif | 1338 | #endif |
1324 | } | 1339 | } |
1325 | 1340 | ||
@@ -1497,13 +1512,15 @@ static int __unlink_module(void *_mod) | |||
1497 | return 0; | 1512 | return 0; |
1498 | } | 1513 | } |
1499 | 1514 | ||
1500 | /* Free a module, remove from lists, etc (must hold module_mutex). */ | 1515 | /* Free a module, remove from lists, etc. */ |
1501 | static void free_module(struct module *mod) | 1516 | static void free_module(struct module *mod) |
1502 | { | 1517 | { |
1503 | trace_module_free(mod); | 1518 | trace_module_free(mod); |
1504 | 1519 | ||
1505 | /* Delete from various lists */ | 1520 | /* Delete from various lists */ |
1521 | mutex_lock(&module_mutex); | ||
1506 | stop_machine(__unlink_module, mod, NULL); | 1522 | stop_machine(__unlink_module, mod, NULL); |
1523 | mutex_unlock(&module_mutex); | ||
1507 | remove_notes_attrs(mod); | 1524 | remove_notes_attrs(mod); |
1508 | remove_sect_attrs(mod); | 1525 | remove_sect_attrs(mod); |
1509 | mod_kobject_remove(mod); | 1526 | mod_kobject_remove(mod); |
@@ -1575,7 +1592,14 @@ static int verify_export_symbols(struct module *mod) | |||
1575 | 1592 | ||
1576 | for (i = 0; i < ARRAY_SIZE(arr); i++) { | 1593 | for (i = 0; i < ARRAY_SIZE(arr); i++) { |
1577 | for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { | 1594 | for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { |
1578 | if (find_symbol(s->name, &owner, NULL, true, false)) { | 1595 | const struct kernel_symbol *sym; |
1596 | |||
1597 | /* Stopping preemption makes find_symbol safe. */ | ||
1598 | preempt_disable(); | ||
1599 | sym = find_symbol(s->name, &owner, NULL, true, false); | ||
1600 | preempt_enable(); | ||
1601 | |||
1602 | if (sym) { | ||
1579 | printk(KERN_ERR | 1603 | printk(KERN_ERR |
1580 | "%s: exports duplicate symbol %s" | 1604 | "%s: exports duplicate symbol %s" |
1581 | " (owned by %s)\n", | 1605 | " (owned by %s)\n", |
@@ -2021,11 +2045,13 @@ static void *module_alloc_update_bounds(unsigned long size) | |||
2021 | void *ret = module_alloc(size); | 2045 | void *ret = module_alloc(size); |
2022 | 2046 | ||
2023 | if (ret) { | 2047 | if (ret) { |
2048 | mutex_lock(&module_mutex); | ||
2024 | /* Update module bounds. */ | 2049 | /* Update module bounds. */ |
2025 | if ((unsigned long)ret < module_addr_min) | 2050 | if ((unsigned long)ret < module_addr_min) |
2026 | module_addr_min = (unsigned long)ret; | 2051 | module_addr_min = (unsigned long)ret; |
2027 | if ((unsigned long)ret + size > module_addr_max) | 2052 | if ((unsigned long)ret + size > module_addr_max) |
2028 | module_addr_max = (unsigned long)ret + size; | 2053 | module_addr_max = (unsigned long)ret + size; |
2054 | mutex_unlock(&module_mutex); | ||
2029 | } | 2055 | } |
2030 | return ret; | 2056 | return ret; |
2031 | } | 2057 | } |
@@ -2482,7 +2508,9 @@ static noinline struct module *load_module(void __user *umod, | |||
2482 | * function to insert in a way safe to concurrent readers. | 2508 | * function to insert in a way safe to concurrent readers. |
2483 | * The mutex protects against concurrent writers. | 2509 | * The mutex protects against concurrent writers. |
2484 | */ | 2510 | */ |
2511 | mutex_lock(&module_mutex); | ||
2485 | list_add_rcu(&mod->list, &modules); | 2512 | list_add_rcu(&mod->list, &modules); |
2513 | mutex_unlock(&module_mutex); | ||
2486 | 2514 | ||
2487 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL); | 2515 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL); |
2488 | if (err < 0) | 2516 | if (err < 0) |
@@ -2504,8 +2532,10 @@ static noinline struct module *load_module(void __user *umod, | |||
2504 | return mod; | 2532 | return mod; |
2505 | 2533 | ||
2506 | unlink: | 2534 | unlink: |
2535 | mutex_lock(&module_mutex); | ||
2507 | /* Unlink carefully: kallsyms could be walking list. */ | 2536 | /* Unlink carefully: kallsyms could be walking list. */ |
2508 | list_del_rcu(&mod->list); | 2537 | list_del_rcu(&mod->list); |
2538 | mutex_unlock(&module_mutex); | ||
2509 | synchronize_sched(); | 2539 | synchronize_sched(); |
2510 | module_arch_cleanup(mod); | 2540 | module_arch_cleanup(mod); |
2511 | cleanup: | 2541 | cleanup: |
@@ -2556,19 +2586,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
2556 | if (!capable(CAP_SYS_MODULE) || modules_disabled) | 2586 | if (!capable(CAP_SYS_MODULE) || modules_disabled) |
2557 | return -EPERM; | 2587 | return -EPERM; |
2558 | 2588 | ||
2559 | /* Only one module load at a time, please */ | ||
2560 | if (mutex_lock_interruptible(&module_mutex) != 0) | ||
2561 | return -EINTR; | ||
2562 | |||
2563 | /* Do all the hard work */ | 2589 | /* Do all the hard work */ |
2564 | mod = load_module(umod, len, uargs); | 2590 | mod = load_module(umod, len, uargs); |
2565 | if (IS_ERR(mod)) { | 2591 | if (IS_ERR(mod)) |
2566 | mutex_unlock(&module_mutex); | ||
2567 | return PTR_ERR(mod); | 2592 | return PTR_ERR(mod); |
2568 | } | ||
2569 | |||
2570 | /* Drop lock so they can recurse */ | ||
2571 | mutex_unlock(&module_mutex); | ||
2572 | 2593 | ||
2573 | blocking_notifier_call_chain(&module_notify_list, | 2594 | blocking_notifier_call_chain(&module_notify_list, |
2574 | MODULE_STATE_COMING, mod); | 2595 | MODULE_STATE_COMING, mod); |
@@ -2585,9 +2606,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
2585 | module_put(mod); | 2606 | module_put(mod); |
2586 | blocking_notifier_call_chain(&module_notify_list, | 2607 | blocking_notifier_call_chain(&module_notify_list, |
2587 | MODULE_STATE_GOING, mod); | 2608 | MODULE_STATE_GOING, mod); |
2588 | mutex_lock(&module_mutex); | ||
2589 | free_module(mod); | 2609 | free_module(mod); |
2590 | mutex_unlock(&module_mutex); | ||
2591 | wake_up(&module_wq); | 2610 | wake_up(&module_wq); |
2592 | return ret; | 2611 | return ret; |
2593 | } | 2612 | } |