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 | |
| 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>
| -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 | } |
