diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/kernel/module.c b/kernel/module.c index e8b51d41dd72..1196f5d11700 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -573,13 +573,13 @@ static char last_unloaded_module[MODULE_NAME_LEN+1]; | |||
573 | /* Init the unload section of the module. */ | 573 | /* Init the unload section of the module. */ |
574 | static void module_unload_init(struct module *mod) | 574 | static void module_unload_init(struct module *mod) |
575 | { | 575 | { |
576 | unsigned int i; | 576 | int cpu; |
577 | 577 | ||
578 | INIT_LIST_HEAD(&mod->modules_which_use_me); | 578 | INIT_LIST_HEAD(&mod->modules_which_use_me); |
579 | for (i = 0; i < NR_CPUS; i++) | 579 | for_each_possible_cpu(cpu) |
580 | local_set(&mod->ref[i].count, 0); | 580 | local_set(__module_ref_addr(mod, cpu), 0); |
581 | /* Hold reference count during initialization. */ | 581 | /* Hold reference count during initialization. */ |
582 | local_set(&mod->ref[raw_smp_processor_id()].count, 1); | 582 | local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1); |
583 | /* Backwards compatibility macros put refcount during init. */ | 583 | /* Backwards compatibility macros put refcount during init. */ |
584 | mod->waiter = current; | 584 | mod->waiter = current; |
585 | } | 585 | } |
@@ -717,10 +717,11 @@ static int try_stop_module(struct module *mod, int flags, int *forced) | |||
717 | 717 | ||
718 | unsigned int module_refcount(struct module *mod) | 718 | unsigned int module_refcount(struct module *mod) |
719 | { | 719 | { |
720 | unsigned int i, total = 0; | 720 | unsigned int total = 0; |
721 | int cpu; | ||
721 | 722 | ||
722 | for (i = 0; i < NR_CPUS; i++) | 723 | for_each_possible_cpu(cpu) |
723 | total += local_read(&mod->ref[i].count); | 724 | total += local_read(__module_ref_addr(mod, cpu)); |
724 | return total; | 725 | return total; |
725 | } | 726 | } |
726 | EXPORT_SYMBOL(module_refcount); | 727 | EXPORT_SYMBOL(module_refcount); |
@@ -894,7 +895,7 @@ void module_put(struct module *module) | |||
894 | { | 895 | { |
895 | if (module) { | 896 | if (module) { |
896 | unsigned int cpu = get_cpu(); | 897 | unsigned int cpu = get_cpu(); |
897 | local_dec(&module->ref[cpu].count); | 898 | local_dec(__module_ref_addr(module, cpu)); |
898 | /* Maybe they're waiting for us to drop reference? */ | 899 | /* Maybe they're waiting for us to drop reference? */ |
899 | if (unlikely(!module_is_live(module))) | 900 | if (unlikely(!module_is_live(module))) |
900 | wake_up_process(module->waiter); | 901 | wake_up_process(module->waiter); |
@@ -1464,7 +1465,10 @@ static void free_module(struct module *mod) | |||
1464 | kfree(mod->args); | 1465 | kfree(mod->args); |
1465 | if (mod->percpu) | 1466 | if (mod->percpu) |
1466 | percpu_modfree(mod->percpu); | 1467 | percpu_modfree(mod->percpu); |
1467 | 1468 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | |
1469 | if (mod->refptr) | ||
1470 | percpu_modfree(mod->refptr); | ||
1471 | #endif | ||
1468 | /* Free lock-classes: */ | 1472 | /* Free lock-classes: */ |
1469 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1473 | lockdep_free_key_range(mod->module_core, mod->core_size); |
1470 | 1474 | ||
@@ -2070,6 +2074,14 @@ static noinline struct module *load_module(void __user *umod, | |||
2070 | /* Module has been moved. */ | 2074 | /* Module has been moved. */ |
2071 | mod = (void *)sechdrs[modindex].sh_addr; | 2075 | mod = (void *)sechdrs[modindex].sh_addr; |
2072 | 2076 | ||
2077 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
2078 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | ||
2079 | mod->name); | ||
2080 | if (!mod->refptr) { | ||
2081 | err = -ENOMEM; | ||
2082 | goto free_init; | ||
2083 | } | ||
2084 | #endif | ||
2073 | /* Now we've moved module, initialize linked lists, etc. */ | 2085 | /* Now we've moved module, initialize linked lists, etc. */ |
2074 | module_unload_init(mod); | 2086 | module_unload_init(mod); |
2075 | 2087 | ||
@@ -2276,9 +2288,14 @@ static noinline struct module *load_module(void __user *umod, | |||
2276 | ftrace_release(mod->module_core, mod->core_size); | 2288 | ftrace_release(mod->module_core, mod->core_size); |
2277 | free_unload: | 2289 | free_unload: |
2278 | module_unload_free(mod); | 2290 | module_unload_free(mod); |
2291 | free_init: | ||
2292 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
2293 | percpu_modfree(mod->refptr); | ||
2294 | #endif | ||
2279 | module_free(mod, mod->module_init); | 2295 | module_free(mod, mod->module_init); |
2280 | free_core: | 2296 | free_core: |
2281 | module_free(mod, mod->module_core); | 2297 | module_free(mod, mod->module_core); |
2298 | /* mod will be freed with core. Don't access it beyond this line! */ | ||
2282 | free_percpu: | 2299 | free_percpu: |
2283 | if (percpu) | 2300 | if (percpu) |
2284 | percpu_modfree(percpu); | 2301 | percpu_modfree(percpu); |