mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
module: extract patient module check into helper
The patient module check inside add_unformed_module() is large enough as we need it. It is a bit hard to read too, so just move it to a helper and do the inverse checks first to help shift the code and make it easier to read. The new helper then is module_patient_check_exists(). To make this work we need to mvoe the finished_loading() up, we do that without making any functional changes to that routine. Reviewed-by: David Hildenbrand <david@redhat.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
This commit is contained in:
parent
25a1b5b518
commit
f71afa6a42
@ -2447,27 +2447,6 @@ static int post_relocation(struct module *mod, const struct load_info *info)
|
|||||||
return module_finalize(info->hdr, info->sechdrs, mod);
|
return module_finalize(info->hdr, info->sechdrs, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this module of this name done loading? No locks held. */
|
|
||||||
static bool finished_loading(const char *name)
|
|
||||||
{
|
|
||||||
struct module *mod;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The module_mutex should not be a heavily contended lock;
|
|
||||||
* if we get the occasional sleep here, we'll go an extra iteration
|
|
||||||
* in the wait_event_interruptible(), which is harmless.
|
|
||||||
*/
|
|
||||||
sched_annotate_sleep();
|
|
||||||
mutex_lock(&module_mutex);
|
|
||||||
mod = find_module_all(name, strlen(name), true);
|
|
||||||
ret = !mod || mod->state == MODULE_STATE_LIVE
|
|
||||||
|| mod->state == MODULE_STATE_GOING;
|
|
||||||
mutex_unlock(&module_mutex);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call module constructors. */
|
/* Call module constructors. */
|
||||||
static void do_mod_ctors(struct module *mod)
|
static void do_mod_ctors(struct module *mod)
|
||||||
{
|
{
|
||||||
@ -2631,34 +2610,49 @@ static int may_init_module(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Is this module of this name done loading? No locks held. */
|
||||||
* We try to place it in the list now to make sure it's unique before
|
static bool finished_loading(const char *name)
|
||||||
* we dedicate too many resources. In particular, temporary percpu
|
|
||||||
* memory exhaustion.
|
|
||||||
*/
|
|
||||||
static int add_unformed_module(struct module *mod)
|
|
||||||
{
|
{
|
||||||
int err;
|
struct module *mod;
|
||||||
struct module *old;
|
bool ret;
|
||||||
|
|
||||||
mod->state = MODULE_STATE_UNFORMED;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The module_mutex should not be a heavily contended lock;
|
||||||
|
* if we get the occasional sleep here, we'll go an extra iteration
|
||||||
|
* in the wait_event_interruptible(), which is harmless.
|
||||||
|
*/
|
||||||
|
sched_annotate_sleep();
|
||||||
mutex_lock(&module_mutex);
|
mutex_lock(&module_mutex);
|
||||||
old = find_module_all(mod->name, strlen(mod->name), true);
|
mod = find_module_all(name, strlen(name), true);
|
||||||
if (old != NULL) {
|
ret = !mod || mod->state == MODULE_STATE_LIVE
|
||||||
if (old->state == MODULE_STATE_COMING
|
|| mod->state == MODULE_STATE_GOING;
|
||||||
|| old->state == MODULE_STATE_UNFORMED) {
|
mutex_unlock(&module_mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must be called with module_mutex held */
|
||||||
|
static int module_patient_check_exists(const char *name)
|
||||||
|
{
|
||||||
|
struct module *old;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
old = find_module_all(name, strlen(name), true);
|
||||||
|
if (old == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (old->state == MODULE_STATE_COMING ||
|
||||||
|
old->state == MODULE_STATE_UNFORMED) {
|
||||||
/* Wait in case it fails to load. */
|
/* Wait in case it fails to load. */
|
||||||
mutex_unlock(&module_mutex);
|
mutex_unlock(&module_mutex);
|
||||||
err = wait_event_interruptible(module_wq,
|
err = wait_event_interruptible(module_wq,
|
||||||
finished_loading(mod->name));
|
finished_loading(name));
|
||||||
|
mutex_lock(&module_mutex);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlocked;
|
return err;
|
||||||
|
|
||||||
/* The module might have gone in the meantime. */
|
/* The module might have gone in the meantime. */
|
||||||
mutex_lock(&module_mutex);
|
old = find_module_all(name, strlen(name), true);
|
||||||
old = find_module_all(mod->name, strlen(mod->name),
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2669,11 +2663,26 @@ static int add_unformed_module(struct module *mod)
|
|||||||
* a particular module.
|
* a particular module.
|
||||||
*/
|
*/
|
||||||
if (old && old->state == MODULE_STATE_LIVE)
|
if (old && old->state == MODULE_STATE_LIVE)
|
||||||
err = -EEXIST;
|
return -EEXIST;
|
||||||
else
|
return -EBUSY;
|
||||||
err = -EBUSY;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We try to place it in the list now to make sure it's unique before
|
||||||
|
* we dedicate too many resources. In particular, temporary percpu
|
||||||
|
* memory exhaustion.
|
||||||
|
*/
|
||||||
|
static int add_unformed_module(struct module *mod)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
mod->state = MODULE_STATE_UNFORMED;
|
||||||
|
|
||||||
|
mutex_lock(&module_mutex);
|
||||||
|
err = module_patient_check_exists(mod->name);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
mod_update_bounds(mod);
|
mod_update_bounds(mod);
|
||||||
list_add_rcu(&mod->list, &modules);
|
list_add_rcu(&mod->list, &modules);
|
||||||
mod_tree_insert(mod);
|
mod_tree_insert(mod);
|
||||||
@ -2681,7 +2690,6 @@ static int add_unformed_module(struct module *mod)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&module_mutex);
|
mutex_unlock(&module_mutex);
|
||||||
out_unlocked:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user