diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 29 | 
1 files changed, 15 insertions, 14 deletions
| diff --git a/kernel/module.c b/kernel/module.c index f82386bd9ee9..e5538d5f00ad 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -474,9 +474,10 @@ static void module_unload_init(struct module *mod) | |||
| 474 | 474 | ||
| 475 | INIT_LIST_HEAD(&mod->modules_which_use_me); | 475 | INIT_LIST_HEAD(&mod->modules_which_use_me); | 
| 476 | for_each_possible_cpu(cpu) | 476 | for_each_possible_cpu(cpu) | 
| 477 | local_set(__module_ref_addr(mod, cpu), 0); | 477 | per_cpu_ptr(mod->refptr, cpu)->count = 0; | 
| 478 | |||
| 478 | /* Hold reference count during initialization. */ | 479 | /* Hold reference count during initialization. */ | 
| 479 | local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1); | 480 | __this_cpu_write(mod->refptr->count, 1); | 
| 480 | /* Backwards compatibility macros put refcount during init. */ | 481 | /* Backwards compatibility macros put refcount during init. */ | 
| 481 | mod->waiter = current; | 482 | mod->waiter = current; | 
| 482 | } | 483 | } | 
| @@ -619,7 +620,7 @@ unsigned int module_refcount(struct module *mod) | |||
| 619 | int cpu; | 620 | int cpu; | 
| 620 | 621 | ||
| 621 | for_each_possible_cpu(cpu) | 622 | for_each_possible_cpu(cpu) | 
| 622 | total += local_read(__module_ref_addr(mod, cpu)); | 623 | total += per_cpu_ptr(mod->refptr, cpu)->count; | 
| 623 | return total; | 624 | return total; | 
| 624 | } | 625 | } | 
| 625 | EXPORT_SYMBOL(module_refcount); | 626 | EXPORT_SYMBOL(module_refcount); | 
| @@ -796,14 +797,15 @@ static struct module_attribute refcnt = { | |||
| 796 | void module_put(struct module *module) | 797 | void module_put(struct module *module) | 
| 797 | { | 798 | { | 
| 798 | if (module) { | 799 | if (module) { | 
| 799 | unsigned int cpu = get_cpu(); | 800 | preempt_disable(); | 
| 800 | local_dec(__module_ref_addr(module, cpu)); | 801 | __this_cpu_dec(module->refptr->count); | 
| 802 | |||
| 801 | trace_module_put(module, _RET_IP_, | 803 | trace_module_put(module, _RET_IP_, | 
| 802 | local_read(__module_ref_addr(module, cpu))); | 804 | __this_cpu_read(module->refptr->count)); | 
| 803 | /* Maybe they're waiting for us to drop reference? */ | 805 | /* Maybe they're waiting for us to drop reference? */ | 
| 804 | if (unlikely(!module_is_live(module))) | 806 | if (unlikely(!module_is_live(module))) | 
| 805 | wake_up_process(module->waiter); | 807 | wake_up_process(module->waiter); | 
| 806 | put_cpu(); | 808 | preempt_enable(); | 
| 807 | } | 809 | } | 
| 808 | } | 810 | } | 
| 809 | EXPORT_SYMBOL(module_put); | 811 | EXPORT_SYMBOL(module_put); | 
| @@ -1397,9 +1399,9 @@ static void free_module(struct module *mod) | |||
| 1397 | kfree(mod->args); | 1399 | kfree(mod->args); | 
| 1398 | if (mod->percpu) | 1400 | if (mod->percpu) | 
| 1399 | percpu_modfree(mod->percpu); | 1401 | percpu_modfree(mod->percpu); | 
| 1400 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 1402 | #if defined(CONFIG_MODULE_UNLOAD) | 
| 1401 | if (mod->refptr) | 1403 | if (mod->refptr) | 
| 1402 | percpu_modfree(mod->refptr); | 1404 | free_percpu(mod->refptr); | 
| 1403 | #endif | 1405 | #endif | 
| 1404 | /* Free lock-classes: */ | 1406 | /* Free lock-classes: */ | 
| 1405 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1407 | lockdep_free_key_range(mod->module_core, mod->core_size); | 
| @@ -2162,9 +2164,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2162 | mod = (void *)sechdrs[modindex].sh_addr; | 2164 | mod = (void *)sechdrs[modindex].sh_addr; | 
| 2163 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); | 2165 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); | 
| 2164 | 2166 | ||
| 2165 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2167 | #if defined(CONFIG_MODULE_UNLOAD) | 
| 2166 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | 2168 | mod->refptr = alloc_percpu(struct module_ref); | 
| 2167 | mod->name); | ||
| 2168 | if (!mod->refptr) { | 2169 | if (!mod->refptr) { | 
| 2169 | err = -ENOMEM; | 2170 | err = -ENOMEM; | 
| 2170 | goto free_init; | 2171 | goto free_init; | 
| @@ -2396,8 +2397,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2396 | kobject_put(&mod->mkobj.kobj); | 2397 | kobject_put(&mod->mkobj.kobj); | 
| 2397 | free_unload: | 2398 | free_unload: | 
| 2398 | module_unload_free(mod); | 2399 | module_unload_free(mod); | 
| 2399 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2400 | #if defined(CONFIG_MODULE_UNLOAD) | 
| 2400 | percpu_modfree(mod->refptr); | 2401 | free_percpu(mod->refptr); | 
| 2401 | free_init: | 2402 | free_init: | 
| 2402 | #endif | 2403 | #endif | 
| 2403 | module_free(mod, mod->module_init); | 2404 | module_free(mod, mod->module_init); | 
