dect
/
linux-2.6
Archived
13
0
Fork 0

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>
This commit is contained in:
Rusty Russell 2010-08-05 12:59:04 -06:00
parent 40dd2560ec
commit 9f85a4bbb1
1 changed files with 15 additions and 17 deletions

View File

@ -524,8 +524,12 @@ static char last_unloaded_module[MODULE_NAME_LEN+1];
EXPORT_TRACEPOINT_SYMBOL(module_get); EXPORT_TRACEPOINT_SYMBOL(module_get);
/* Init the unload section of the module. */ /* Init the unload section of the module. */
static void module_unload_init(struct module *mod) static int module_unload_init(struct module *mod)
{ {
mod->refptr = alloc_percpu(struct module_ref);
if (!mod->refptr)
return -ENOMEM;
INIT_LIST_HEAD(&mod->source_list); INIT_LIST_HEAD(&mod->source_list);
INIT_LIST_HEAD(&mod->target_list); INIT_LIST_HEAD(&mod->target_list);
@ -533,6 +537,8 @@ static void module_unload_init(struct module *mod)
__this_cpu_write(mod->refptr->incs, 1); __this_cpu_write(mod->refptr->incs, 1);
/* Backwards compatibility macros put refcount during init. */ /* Backwards compatibility macros put refcount during init. */
mod->waiter = current; mod->waiter = current;
return 0;
} }
/* Does a already use b? */ /* Does a already use b? */
@ -612,6 +618,8 @@ static void module_unload_free(struct module *mod)
kfree(use); kfree(use);
} }
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
free_percpu(mod->refptr);
} }
#ifdef CONFIG_MODULE_FORCE_UNLOAD #ifdef CONFIG_MODULE_FORCE_UNLOAD
@ -885,8 +893,9 @@ int ref_module(struct module *a, struct module *b)
} }
EXPORT_SYMBOL_GPL(ref_module); EXPORT_SYMBOL_GPL(ref_module);
static inline void module_unload_init(struct module *mod) static inline int module_unload_init(struct module *mod)
{ {
return 0;
} }
#endif /* CONFIG_MODULE_UNLOAD */ #endif /* CONFIG_MODULE_UNLOAD */
@ -1559,10 +1568,7 @@ static void free_module(struct module *mod)
module_free(mod, mod->module_init); module_free(mod, mod->module_init);
kfree(mod->args); kfree(mod->args);
percpu_modfree(mod); percpu_modfree(mod);
#if defined(CONFIG_MODULE_UNLOAD)
if (mod->refptr)
free_percpu(mod->refptr);
#endif
/* Free lock-classes: */ /* Free lock-classes: */
lockdep_free_key_range(mod->module_core, mod->core_size); lockdep_free_key_range(mod->module_core, mod->core_size);
@ -2442,15 +2448,10 @@ static noinline struct module *load_module(void __user *umod,
goto free_percpu; goto free_percpu;
} }
#if defined(CONFIG_MODULE_UNLOAD)
mod->refptr = alloc_percpu(struct module_ref);
if (!mod->refptr) {
err = -ENOMEM;
goto free_init;
}
#endif
/* Now we've moved module, initialize linked lists, etc. */ /* Now we've moved module, initialize linked lists, etc. */
module_unload_init(mod); err = module_unload_init(mod);
if (err)
goto free_init;
/* Set up license info based on the info section */ /* Set up license info based on the info section */
set_license(mod, get_modinfo(sechdrs, infoindex, "license")); set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
@ -2619,10 +2620,7 @@ static noinline struct module *load_module(void __user *umod,
cleanup: cleanup:
free_modinfo(mod); free_modinfo(mod);
module_unload_free(mod); module_unload_free(mod);
#if defined(CONFIG_MODULE_UNLOAD)
free_percpu(mod->refptr);
free_init: free_init:
#endif
module_free(mod, mod->module_init); module_free(mod, mod->module_init);
module_free(mod, mod->module_core); module_free(mod, mod->module_core);
/* mod will be freed with core. Don't access it beyond this line! */ /* mod will be freed with core. Don't access it beyond this line! */