diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/kernel/module.c b/kernel/module.c index f82386bd9ee9..c968d3606dca 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); |
@@ -1083,6 +1085,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
1083 | if (sattr->name == NULL) | 1085 | if (sattr->name == NULL) |
1084 | goto out; | 1086 | goto out; |
1085 | sect_attrs->nsections++; | 1087 | sect_attrs->nsections++; |
1088 | sysfs_attr_init(&sattr->mattr.attr); | ||
1086 | sattr->mattr.show = module_sect_show; | 1089 | sattr->mattr.show = module_sect_show; |
1087 | sattr->mattr.store = NULL; | 1090 | sattr->mattr.store = NULL; |
1088 | sattr->mattr.attr.name = sattr->name; | 1091 | sattr->mattr.attr.name = sattr->name; |
@@ -1178,6 +1181,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, | |||
1178 | if (sect_empty(&sechdrs[i])) | 1181 | if (sect_empty(&sechdrs[i])) |
1179 | continue; | 1182 | continue; |
1180 | if (sechdrs[i].sh_type == SHT_NOTE) { | 1183 | if (sechdrs[i].sh_type == SHT_NOTE) { |
1184 | sysfs_bin_attr_init(nattr); | ||
1181 | nattr->attr.name = mod->sect_attrs->attrs[loaded].name; | 1185 | nattr->attr.name = mod->sect_attrs->attrs[loaded].name; |
1182 | nattr->attr.mode = S_IRUGO; | 1186 | nattr->attr.mode = S_IRUGO; |
1183 | nattr->size = sechdrs[i].sh_size; | 1187 | nattr->size = sechdrs[i].sh_size; |
@@ -1250,6 +1254,7 @@ int module_add_modinfo_attrs(struct module *mod) | |||
1250 | if (!attr->test || | 1254 | if (!attr->test || |
1251 | (attr->test && attr->test(mod))) { | 1255 | (attr->test && attr->test(mod))) { |
1252 | memcpy(temp_attr, attr, sizeof(*temp_attr)); | 1256 | memcpy(temp_attr, attr, sizeof(*temp_attr)); |
1257 | sysfs_attr_init(&temp_attr->attr); | ||
1253 | error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); | 1258 | error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); |
1254 | ++temp_attr; | 1259 | ++temp_attr; |
1255 | } | 1260 | } |
@@ -1397,9 +1402,9 @@ static void free_module(struct module *mod) | |||
1397 | kfree(mod->args); | 1402 | kfree(mod->args); |
1398 | if (mod->percpu) | 1403 | if (mod->percpu) |
1399 | percpu_modfree(mod->percpu); | 1404 | percpu_modfree(mod->percpu); |
1400 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 1405 | #if defined(CONFIG_MODULE_UNLOAD) |
1401 | if (mod->refptr) | 1406 | if (mod->refptr) |
1402 | percpu_modfree(mod->refptr); | 1407 | free_percpu(mod->refptr); |
1403 | #endif | 1408 | #endif |
1404 | /* Free lock-classes: */ | 1409 | /* Free lock-classes: */ |
1405 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1410 | lockdep_free_key_range(mod->module_core, mod->core_size); |
@@ -2162,9 +2167,8 @@ static noinline struct module *load_module(void __user *umod, | |||
2162 | mod = (void *)sechdrs[modindex].sh_addr; | 2167 | mod = (void *)sechdrs[modindex].sh_addr; |
2163 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); | 2168 | kmemleak_load_module(mod, hdr, sechdrs, secstrings); |
2164 | 2169 | ||
2165 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2170 | #if defined(CONFIG_MODULE_UNLOAD) |
2166 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | 2171 | mod->refptr = alloc_percpu(struct module_ref); |
2167 | mod->name); | ||
2168 | if (!mod->refptr) { | 2172 | if (!mod->refptr) { |
2169 | err = -ENOMEM; | 2173 | err = -ENOMEM; |
2170 | goto free_init; | 2174 | goto free_init; |
@@ -2396,8 +2400,8 @@ static noinline struct module *load_module(void __user *umod, | |||
2396 | kobject_put(&mod->mkobj.kobj); | 2400 | kobject_put(&mod->mkobj.kobj); |
2397 | free_unload: | 2401 | free_unload: |
2398 | module_unload_free(mod); | 2402 | module_unload_free(mod); |
2399 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | 2403 | #if defined(CONFIG_MODULE_UNLOAD) |
2400 | percpu_modfree(mod->refptr); | 2404 | free_percpu(mod->refptr); |
2401 | free_init: | 2405 | free_init: |
2402 | #endif | 2406 | #endif |
2403 | module_free(mod, mod->module_init); | 2407 | module_free(mod, mod->module_init); |