67 lines
2.2 KiB
Diff
67 lines
2.2 KiB
Diff
From: Rusty Russell <rusty@rustcorp.com.au>
|
|
Date: Fri, 28 Sep 2012 05:01:03 +0000 (+0930)
|
|
Subject: module: fix symbol waiting when module fails before init
|
|
X-Git-Tag: v3.7-rc1~2^2~33
|
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=6f13909f4fe9652f1
|
|
|
|
module: fix symbol waiting when module fails before init
|
|
|
|
We use resolve_symbol_wait(), which blocks if the module containing
|
|
the symbol is still loading. However:
|
|
|
|
1) The module_wq we use is only woken after calling the modules' init
|
|
function, but there are other failure paths after the module is
|
|
placed in the linked list where we need to do the same thing.
|
|
|
|
2) wake_up() only wakes one waiter, and our waitqueue is shared by all
|
|
modules, so we need to wake them all.
|
|
|
|
3) wake_up_all() doesn't imply a memory barrier: I feel happier calling
|
|
it after we've grabbed and dropped the module_mutex, not just after
|
|
the state assignment.
|
|
|
|
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
|
|
---
|
|
|
|
diff --git a/kernel/module.c b/kernel/module.c
|
|
index 7f2ee45f..63cf6e7 100644
|
|
--- a/kernel/module.c
|
|
+++ b/kernel/module.c
|
|
@@ -2959,7 +2959,7 @@ static struct module *load_module(void __user *umod,
|
|
/* Unlink carefully: kallsyms could be walking list. */
|
|
list_del_rcu(&mod->list);
|
|
module_bug_cleanup(mod);
|
|
-
|
|
+ wake_up_all(&module_wq);
|
|
ddebug:
|
|
dynamic_debug_remove(info.debug);
|
|
unlock:
|
|
@@ -3034,7 +3034,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_GOING, mod);
|
|
free_module(mod);
|
|
- wake_up(&module_wq);
|
|
+ wake_up_all(&module_wq);
|
|
return ret;
|
|
}
|
|
if (ret > 0) {
|
|
@@ -3046,9 +3046,8 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
|
|
dump_stack();
|
|
}
|
|
|
|
- /* Now it's a first class citizen! Wake up anyone waiting for it. */
|
|
+ /* Now it's a first class citizen! */
|
|
mod->state = MODULE_STATE_LIVE;
|
|
- wake_up(&module_wq);
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
MODULE_STATE_LIVE, mod);
|
|
|
|
@@ -3071,6 +3070,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
|
|
mod->init_ro_size = 0;
|
|
mod->init_text_size = 0;
|
|
mutex_unlock(&module_mutex);
|
|
+ wake_up_all(&module_wq);
|
|
|
|
return 0;
|
|
}
|