diff options
Diffstat (limited to 'kernel')
| -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 e96b8ed1cb6a..9bf228052ec5 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); | 
| @@ -1394,9 +1396,9 @@ static void free_module(struct module *mod) | |||
| 1394 | kfree(mod->args); | 1396 | kfree(mod->args); | 
| 1395 | if (mod->percpu) | 1397 | if (mod->percpu) | 
| 1396 | percpu_modfree(mod->percpu); | 1398 | percpu_modfree(mod->percpu); | 
| 1397 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 1399 | #if defined(CONFIG_MODULE_UNLOAD) | 
| 1398 | if (mod->refptr) | 1400 | if (mod->refptr) | 
| 1399 | percpu_modfree(mod->refptr); | 1401 | free_percpu(mod->refptr); | 
| 1400 | #endif | 1402 | #endif | 
| 1401 | /* Free lock-classes: */ | 1403 | /* Free lock-classes: */ | 
| 1402 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1404 | lockdep_free_key_range(mod->module_core, mod->core_size); | 
| @@ -2159,9 +2161,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2159 | mod = (void *)sechdrs[modindex].sh_addr; | 2161 | mod = (void *)sechdrs[modindex].sh_addr; | 
| 2160 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); | 2162 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); | 
| 2161 | 2163 | ||
| 2162 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2164 | #if defined(CONFIG_MODULE_UNLOAD) | 
| 2163 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | 2165 | mod->refptr = alloc_percpu(struct module_ref); | 
| 2164 | mod->name); | ||
| 2165 | if (!mod->refptr) { | 2166 | if (!mod->refptr) { | 
| 2166 | err = -ENOMEM; | 2167 | err = -ENOMEM; | 
| 2167 | goto free_init; | 2168 | goto free_init; | 
| @@ -2393,8 +2394,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2393 | kobject_put(&mod->mkobj.kobj); | 2394 | kobject_put(&mod->mkobj.kobj); | 
| 2394 | free_unload: | 2395 | free_unload: | 
| 2395 | module_unload_free(mod); | 2396 | module_unload_free(mod); | 
| 2396 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2397 | #if defined(CONFIG_MODULE_UNLOAD) | 
| 2397 | percpu_modfree(mod->refptr); | 2398 | free_percpu(mod->refptr); | 
| 2398 | free_init: | 2399 | free_init: | 
| 2399 | #endif | 2400 | #endif | 
| 2400 | module_free(mod, mod->module_init); | 2401 | module_free(mod, mod->module_init); | 
