1 |
From 9bb9c3be56834653878f766f471fa1c20e562f4c Mon Sep 17 00:00:00 2001 |
2 |
From: Rusty Russell <rusty@rustcorp.com.au> |
3 |
Date: Fri, 28 Sep 2012 14:31:03 +0930 |
4 |
Subject: [PATCH] module: wait when loading a module which is currently |
5 |
initializing. |
6 |
|
7 |
The original module-init-tools module loader used a fnctl lock on the |
8 |
.ko file to avoid attempts to simultaneously load a module. |
9 |
Unfortunately, you can't get an exclusive fcntl lock on a read-only |
10 |
fd, making this not work for read-only mounted filesystems. |
11 |
module-init-tools has a hacky sleep-and-loop for this now. |
12 |
|
13 |
It's not that hard to wait in the kernel, and only return -EEXIST once |
14 |
the first module has finished loading (or continue loading the module |
15 |
if the first one failed to initialize for some reason). It's also |
16 |
consistent with what we do for dependent modules which are still loading. |
17 |
|
18 |
Suggested-by: Lucas De Marchi <lucas.demarchi@profusion.mobi> |
19 |
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> |
20 |
--- |
21 |
kernel/module.c | 28 ++++++++++++++++++++++++++-- |
22 |
1 file changed, 26 insertions(+), 2 deletions(-) |
23 |
|
24 |
diff --git a/kernel/module.c b/kernel/module.c |
25 |
index 63cf6e7..74bc195 100644 |
26 |
--- a/kernel/module.c |
27 |
+++ b/kernel/module.c |
28 |
@@ -2845,6 +2845,20 @@ static int post_relocation(struct module *mod, const struct load_info *info) |
29 |
return module_finalize(info->hdr, info->sechdrs, mod); |
30 |
} |
31 |
|
32 |
+/* Is this module of this name done loading? No locks held. */ |
33 |
+static bool finished_loading(const char *name) |
34 |
+{ |
35 |
+ struct module *mod; |
36 |
+ bool ret; |
37 |
+ |
38 |
+ mutex_lock(&module_mutex); |
39 |
+ mod = find_module(name); |
40 |
+ ret = !mod || mod->state != MODULE_STATE_COMING; |
41 |
+ mutex_unlock(&module_mutex); |
42 |
+ |
43 |
+ return ret; |
44 |
+} |
45 |
+ |
46 |
/* Allocate and load the module: note that size of section 0 is always |
47 |
zero, and we rely on this for optional sections. */ |
48 |
static struct module *load_module(void __user *umod, |
49 |
@@ -2852,7 +2866,7 @@ static struct module *load_module(void __user *umod, |
50 |
const char __user *uargs) |
51 |
{ |
52 |
struct load_info info = { NULL, }; |
53 |
- struct module *mod; |
54 |
+ struct module *mod, *old; |
55 |
long err; |
56 |
|
57 |
pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", |
58 |
@@ -2918,8 +2932,18 @@ static struct module *load_module(void __user *umod, |
59 |
* function to insert in a way safe to concurrent readers. |
60 |
* The mutex protects against concurrent writers. |
61 |
*/ |
62 |
+again: |
63 |
mutex_lock(&module_mutex); |
64 |
- if (find_module(mod->name)) { |
65 |
+ if ((old = find_module(mod->name)) != NULL) { |
66 |
+ if (old->state == MODULE_STATE_COMING) { |
67 |
+ /* Wait in case it fails to load. */ |
68 |
+ mutex_unlock(&module_mutex); |
69 |
+ err = wait_event_interruptible(module_wq, |
70 |
+ finished_loading(mod->name)); |
71 |
+ if (err) |
72 |
+ goto free_arch_cleanup; |
73 |
+ goto again; |
74 |
+ } |
75 |
err = -EEXIST; |
76 |
goto unlock; |
77 |
} |
78 |
-- |
79 |
1.7.12.4 |
80 |
|