aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2010-08-05 14:59:04 -0400
committerRusty Russell <rusty@rustcorp.com.au>2010-08-04 23:29:05 -0400
commit9f85a4bbb1cf56f65b3d065a5f88204a757f2325 (patch)
tree28d674a40dcab0e0c31349736718993f1e9377d4 /kernel/module.c
parent40dd2560ec2df21036db9ec8b971f92d98fd1969 (diff)
module: refactor load_module part 4
Allocate references inside module_unload_init(), clean up inside module_unload_free(). This version fixed to do allocation before __this_cpu_write, thanks to bug reports from linux-next from Dave Young <hidave.darkstar@gmail.com> and Stephen Rothwell <sfr@canb.auug.org.au>. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c32
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];
524EXPORT_TRACEPOINT_SYMBOL(module_get); 524EXPORT_TRACEPOINT_SYMBOL(module_get);
525 525
526/* Init the unload section of the module. */ 526/* Init the unload section of the module. */
527static void module_unload_init(struct module *mod) 527static 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}
886EXPORT_SYMBOL_GPL(ref_module); 894EXPORT_SYMBOL_GPL(ref_module);
887 895
888static inline void module_unload_init(struct module *mod) 896static 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! */