diff options
Diffstat (limited to 'core/linux-lts/module-init-wait-3.0.patch')
-rw-r--r-- | core/linux-lts/module-init-wait-3.0.patch | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/core/linux-lts/module-init-wait-3.0.patch b/core/linux-lts/module-init-wait-3.0.patch new file mode 100644 index 000000000..1bcfd2491 --- /dev/null +++ b/core/linux-lts/module-init-wait-3.0.patch @@ -0,0 +1,77 @@ +From: Rusty Russell <rusty@rustcorp.com.au> +Date: Fri, 28 Sep 2012 05:01:03 +0000 (+0930) +Subject: module: wait when loading a module which is currently initializing. +X-Git-Tag: v3.7-rc1~2^2~32 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9bb9c3be568346538 + +module: wait when loading a module which is currently initializing. + +The original module-init-tools module loader used a fnctl lock on the +.ko file to avoid attempts to simultaneously load a module. +Unfortunately, you can't get an exclusive fcntl lock on a read-only +fd, making this not work for read-only mounted filesystems. +module-init-tools has a hacky sleep-and-loop for this now. + +It's not that hard to wait in the kernel, and only return -EEXIST once +the first module has finished loading (or continue loading the module +if the first one failed to initialize for some reason). It's also +consistent with what we do for dependent modules which are still loading. + +Suggested-by: Lucas De Marchi <lucas.demarchi@profusion.mobi> +Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> +--- + +diff --git a/kernel/module.c b/kernel/module.c +index 63cf6e7..74bc195 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2845,6 +2845,20 @@ 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; ++ ++ mutex_lock(&module_mutex); ++ mod = find_module(name); ++ ret = !mod || mod->state != MODULE_STATE_COMING; ++ mutex_unlock(&module_mutex); ++ ++ return ret; ++} ++ + /* Allocate and load the module: note that size of section 0 is always + zero, and we rely on this for optional sections. */ + static struct module *load_module(void __user *umod, +@@ -2852,7 +2866,7 @@ static struct module *load_module(void __user *umod, + const char __user *uargs) + { + struct load_info info = { NULL, }; +- struct module *mod; ++ struct module *mod, *old; + long err; + + pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", +@@ -2918,8 +2932,18 @@ static struct module *load_module(void __user *umod, + * function to insert in a way safe to concurrent readers. + * The mutex protects against concurrent writers. + */ ++again: + mutex_lock(&module_mutex); +- if (find_module(mod->name)) { ++ if ((old = find_module(mod->name)) != NULL) { ++ if (old->state == MODULE_STATE_COMING) { ++ /* Wait in case it fails to load. */ ++ mutex_unlock(&module_mutex); ++ err = wait_event_interruptible(module_wq, ++ finished_loading(mod->name)); ++ if (err) ++ goto free_arch_cleanup; ++ goto again; ++ } + err = -EEXIST; + goto unlock; + } |