Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f85a4bb authored by Rusty Russell's avatar Rusty Russell
Browse files

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: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 40dd2560
Loading
Loading
Loading
Loading
+15 −17
Original line number Diff line number Diff line
@@ -524,8 +524,12 @@ static char last_unloaded_module[MODULE_NAME_LEN+1];
EXPORT_TRACEPOINT_SYMBOL(module_get);

/* 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->target_list);

@@ -533,6 +537,8 @@ static void module_unload_init(struct module *mod)
	__this_cpu_write(mod->refptr->incs, 1);
	/* Backwards compatibility macros put refcount during init. */
	mod->waiter = current;

	return 0;
}

/* Does a already use b? */
@@ -612,6 +618,8 @@ static void module_unload_free(struct module *mod)
		kfree(use);
	}
	mutex_unlock(&module_mutex);

	free_percpu(mod->refptr);
}

#ifdef CONFIG_MODULE_FORCE_UNLOAD
@@ -885,8 +893,9 @@ int ref_module(struct module *a, struct module *b)
}
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 */

@@ -1559,10 +1568,7 @@ static void free_module(struct module *mod)
	module_free(mod, mod->module_init);
	kfree(mod->args);
	percpu_modfree(mod);
#if defined(CONFIG_MODULE_UNLOAD)
	if (mod->refptr)
		free_percpu(mod->refptr);
#endif

	/* Free lock-classes: */
	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;
	}

#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. */
	module_unload_init(mod);
	err = module_unload_init(mod);
	if (err)
		goto free_init;

	/* Set up license info based on the info section */
	set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
@@ -2619,10 +2620,7 @@ static noinline struct module *load_module(void __user *umod,
 cleanup:
	free_modinfo(mod);
	module_unload_free(mod);
#if defined(CONFIG_MODULE_UNLOAD)
	free_percpu(mod->refptr);
 free_init:
#endif
	module_free(mod, mod->module_init);
	module_free(mod, mod->module_core);
	/* mod will be freed with core. Don't access it beyond this line! */