Commit f71afa6a authored by Luis Chamberlain's avatar Luis Chamberlain
Browse files

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: default avatarDavid Hildenbrand <david@redhat.com>
Signed-off-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
parent 25a1b5b5
Loading
Loading
Loading
Loading
+60 −52
Original line number Diff line number Diff line
@@ -2447,27 +2447,6 @@ static int post_relocation(struct module *mod, const struct load_info *info)
	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. */
static void do_mod_ctors(struct module *mod)
{
@@ -2631,34 +2610,49 @@ static int may_init_module(void)
	return 0;
}

/* Is this module of this name done loading?  No locks held. */
static bool finished_loading(const char *name)
{
	struct module *mod;
	bool ret;

	/*
 * 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.
	 * 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.
	 */
static int add_unformed_module(struct module *mod)
	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;
}

/* Must be called with module_mutex held */
static int module_patient_check_exists(const char *name)
{
	int err;
	struct module *old;
	int err = 0;

	mod->state = MODULE_STATE_UNFORMED;
	old = find_module_all(name, strlen(name), true);
	if (old == NULL)
		return 0;

	mutex_lock(&module_mutex);
	old = find_module_all(mod->name, strlen(mod->name), true);
	if (old != NULL) {
		if (old->state == MODULE_STATE_COMING
		    || old->state == MODULE_STATE_UNFORMED) {
	if (old->state == MODULE_STATE_COMING ||
	    old->state == MODULE_STATE_UNFORMED) {
		/* Wait in case it fails to load. */
		mutex_unlock(&module_mutex);
		err = wait_event_interruptible(module_wq,
					       finished_loading(mod->name));
				       finished_loading(name));
		mutex_lock(&module_mutex);
		if (err)
				goto out_unlocked;
			return err;

		/* The module might have gone in the meantime. */
			mutex_lock(&module_mutex);
			old = find_module_all(mod->name, strlen(mod->name),
					      true);
		old = find_module_all(name, strlen(name), true);
	}

	/*
@@ -2669,11 +2663,26 @@ static int add_unformed_module(struct module *mod)
	 * a particular module.
	 */
	if (old && old->state == MODULE_STATE_LIVE)
			err = -EEXIST;
		else
			err = -EBUSY;
		goto out;
		return -EEXIST;
	return -EBUSY;
}

/*
 * 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);
	list_add_rcu(&mod->list, &modules);
	mod_tree_insert(mod);
@@ -2681,7 +2690,6 @@ static int add_unformed_module(struct module *mod)

out:
	mutex_unlock(&module_mutex);
out_unlocked:
	return err;
}