diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/kernel/module.c b/kernel/module.c index c9332c90d5a0..ba22484a987e 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); |
| @@ -743,8 +744,8 @@ static void wait_for_zero_refcount(struct module *mod) | |||
| 743 | mutex_lock(&module_mutex); | 744 | mutex_lock(&module_mutex); |
| 744 | } | 745 | } |
| 745 | 746 | ||
| 746 | asmlinkage long | 747 | SYSCALL_DEFINE2(delete_module, const char __user *, name_user, |
| 747 | sys_delete_module(const char __user *name_user, unsigned int flags) | 748 | unsigned int, flags) |
| 748 | { | 749 | { |
| 749 | struct module *mod; | 750 | struct module *mod; |
| 750 | char name[MODULE_NAME_LEN]; | 751 | char name[MODULE_NAME_LEN]; |
| @@ -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 | ||
| @@ -2011,6 +2015,14 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2011 | if (err < 0) | 2015 | if (err < 0) |
| 2012 | goto free_mod; | 2016 | goto free_mod; |
| 2013 | 2017 | ||
| 2018 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2019 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | ||
| 2020 | mod->name); | ||
| 2021 | if (!mod->refptr) { | ||
| 2022 | err = -ENOMEM; | ||
| 2023 | goto free_mod; | ||
| 2024 | } | ||
| 2025 | #endif | ||
| 2014 | if (pcpuindex) { | 2026 | if (pcpuindex) { |
| 2015 | /* We have a special allocation for this section. */ | 2027 | /* We have a special allocation for this section. */ |
| 2016 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, | 2028 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, |
| @@ -2018,7 +2030,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2018 | mod->name); | 2030 | mod->name); |
| 2019 | if (!percpu) { | 2031 | if (!percpu) { |
| 2020 | err = -ENOMEM; | 2032 | err = -ENOMEM; |
| 2021 | goto free_mod; | 2033 | goto free_percpu; |
| 2022 | } | 2034 | } |
| 2023 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2035 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2024 | mod->percpu = percpu; | 2036 | mod->percpu = percpu; |
| @@ -2282,6 +2294,9 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2282 | free_percpu: | 2294 | free_percpu: |
| 2283 | if (percpu) | 2295 | if (percpu) |
| 2284 | percpu_modfree(percpu); | 2296 | percpu_modfree(percpu); |
| 2297 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
| 2298 | percpu_modfree(mod->refptr); | ||
| 2299 | #endif | ||
| 2285 | free_mod: | 2300 | free_mod: |
| 2286 | kfree(args); | 2301 | kfree(args); |
| 2287 | free_hdr: | 2302 | free_hdr: |
| @@ -2296,10 +2311,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2296 | } | 2311 | } |
| 2297 | 2312 | ||
| 2298 | /* This is where the real work happens */ | 2313 | /* This is where the real work happens */ |
| 2299 | asmlinkage long | 2314 | SYSCALL_DEFINE3(init_module, void __user *, umod, |
| 2300 | sys_init_module(void __user *umod, | 2315 | unsigned long, len, const char __user *, uargs) |
| 2301 | unsigned long len, | ||
| 2302 | const char __user *uargs) | ||
| 2303 | { | 2316 | { |
| 2304 | struct module *mod; | 2317 | struct module *mod; |
| 2305 | int ret = 0; | 2318 | int ret = 0; |
