diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/kernel/module.c b/kernel/module.c index d8faf35cba84..241bc41dd6be 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -524,8 +524,12 @@ static char last_unloaded_module[MODULE_NAME_LEN+1]; | |||
| 524 | EXPORT_TRACEPOINT_SYMBOL(module_get); | 524 | EXPORT_TRACEPOINT_SYMBOL(module_get); |
| 525 | 525 | ||
| 526 | /* Init the unload section of the module. */ | 526 | /* Init the unload section of the module. */ |
| 527 | static void module_unload_init(struct module *mod) | 527 | static int module_unload_init(struct module *mod) |
| 528 | { | 528 | { |
| 529 | mod->refptr = alloc_percpu(struct module_ref); | ||
| 530 | if (!mod->refptr) | ||
| 531 | return -ENOMEM; | ||
| 532 | |||
| 529 | INIT_LIST_HEAD(&mod->source_list); | 533 | INIT_LIST_HEAD(&mod->source_list); |
| 530 | INIT_LIST_HEAD(&mod->target_list); | 534 | INIT_LIST_HEAD(&mod->target_list); |
| 531 | 535 | ||
| @@ -533,6 +537,8 @@ static void module_unload_init(struct module *mod) | |||
| 533 | __this_cpu_write(mod->refptr->incs, 1); | 537 | __this_cpu_write(mod->refptr->incs, 1); |
| 534 | /* Backwards compatibility macros put refcount during init. */ | 538 | /* Backwards compatibility macros put refcount during init. */ |
| 535 | mod->waiter = current; | 539 | mod->waiter = current; |
| 540 | |||
| 541 | return 0; | ||
| 536 | } | 542 | } |
| 537 | 543 | ||
| 538 | /* Does a already use b? */ | 544 | /* Does a already use b? */ |
| @@ -612,6 +618,8 @@ static void module_unload_free(struct module *mod) | |||
| 612 | kfree(use); | 618 | kfree(use); |
| 613 | } | 619 | } |
| 614 | mutex_unlock(&module_mutex); | 620 | mutex_unlock(&module_mutex); |
| 621 | |||
| 622 | free_percpu(mod->refptr); | ||
| 615 | } | 623 | } |
| 616 | 624 | ||
| 617 | #ifdef CONFIG_MODULE_FORCE_UNLOAD | 625 | #ifdef CONFIG_MODULE_FORCE_UNLOAD |
| @@ -885,8 +893,9 @@ int ref_module(struct module *a, struct module *b) | |||
| 885 | } | 893 | } |
| 886 | EXPORT_SYMBOL_GPL(ref_module); | 894 | EXPORT_SYMBOL_GPL(ref_module); |
| 887 | 895 | ||
| 888 | static inline void module_unload_init(struct module *mod) | 896 | static inline int module_unload_init(struct module *mod) |
| 889 | { | 897 | { |
| 898 | return 0; | ||
| 890 | } | 899 | } |
| 891 | #endif /* CONFIG_MODULE_UNLOAD */ | 900 | #endif /* CONFIG_MODULE_UNLOAD */ |
| 892 | 901 | ||
| @@ -1559,10 +1568,7 @@ static void free_module(struct module *mod) | |||
| 1559 | module_free(mod, mod->module_init); | 1568 | module_free(mod, mod->module_init); |
| 1560 | kfree(mod->args); | 1569 | kfree(mod->args); |
| 1561 | percpu_modfree(mod); | 1570 | percpu_modfree(mod); |
| 1562 | #if defined(CONFIG_MODULE_UNLOAD) | 1571 | |
| 1563 | if (mod->refptr) | ||
| 1564 | free_percpu(mod->refptr); | ||
| 1565 | #endif | ||
| 1566 | /* Free lock-classes: */ | 1572 | /* Free lock-classes: */ |
| 1567 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1573 | lockdep_free_key_range(mod->module_core, mod->core_size); |
| 1568 | 1574 | ||
| @@ -2442,15 +2448,10 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2442 | goto free_percpu; | 2448 | goto free_percpu; |
| 2443 | } | 2449 | } |
| 2444 | 2450 | ||
| 2445 | #if defined(CONFIG_MODULE_UNLOAD) | ||
| 2446 | mod->refptr = alloc_percpu(struct module_ref); | ||
| 2447 | if (!mod->refptr) { | ||
| 2448 | err = -ENOMEM; | ||
| 2449 | goto free_init; | ||
| 2450 | } | ||
| 2451 | #endif | ||
| 2452 | /* Now we've moved module, initialize linked lists, etc. */ | 2451 | /* Now we've moved module, initialize linked lists, etc. */ |
| 2453 | module_unload_init(mod); | 2452 | err = module_unload_init(mod); |
| 2453 | if (err) | ||
| 2454 | goto free_init; | ||
| 2454 | 2455 | ||
| 2455 | /* Set up license info based on the info section */ | 2456 | /* Set up license info based on the info section */ |
| 2456 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | 2457 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); |
| @@ -2619,10 +2620,7 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2619 | cleanup: | 2620 | cleanup: |
| 2620 | free_modinfo(mod); | 2621 | free_modinfo(mod); |
| 2621 | module_unload_free(mod); | 2622 | module_unload_free(mod); |
| 2622 | #if defined(CONFIG_MODULE_UNLOAD) | ||
| 2623 | free_percpu(mod->refptr); | ||
| 2624 | free_init: | 2623 | free_init: |
| 2625 | #endif | ||
| 2626 | module_free(mod, mod->module_init); | 2624 | module_free(mod, mod->module_init); |
| 2627 | module_free(mod, mod->module_core); | 2625 | module_free(mod, mod->module_core); |
| 2628 | /* mod will be freed with core. Don't access it beyond this line! */ | 2626 | /* mod will be freed with core. Don't access it beyond this line! */ |
