diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/kernel/module.c b/kernel/module.c index 250092c1d57d..b10b048367e1 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -3013,6 +3013,12 @@ static int do_init_module(struct module *mod) | |||
3013 | { | 3013 | { |
3014 | int ret = 0; | 3014 | int ret = 0; |
3015 | 3015 | ||
3016 | /* | ||
3017 | * We want to find out whether @mod uses async during init. Clear | ||
3018 | * PF_USED_ASYNC. async_schedule*() will set it. | ||
3019 | */ | ||
3020 | current->flags &= ~PF_USED_ASYNC; | ||
3021 | |||
3016 | blocking_notifier_call_chain(&module_notify_list, | 3022 | blocking_notifier_call_chain(&module_notify_list, |
3017 | MODULE_STATE_COMING, mod); | 3023 | MODULE_STATE_COMING, mod); |
3018 | 3024 | ||
@@ -3058,8 +3064,25 @@ static int do_init_module(struct module *mod) | |||
3058 | blocking_notifier_call_chain(&module_notify_list, | 3064 | blocking_notifier_call_chain(&module_notify_list, |
3059 | MODULE_STATE_LIVE, mod); | 3065 | MODULE_STATE_LIVE, mod); |
3060 | 3066 | ||
3061 | /* We need to finish all async code before the module init sequence is done */ | 3067 | /* |
3062 | async_synchronize_full(); | 3068 | * We need to finish all async code before the module init sequence |
3069 | * is done. This has potential to deadlock. For example, a newly | ||
3070 | * detected block device can trigger request_module() of the | ||
3071 | * default iosched from async probing task. Once userland helper | ||
3072 | * reaches here, async_synchronize_full() will wait on the async | ||
3073 | * task waiting on request_module() and deadlock. | ||
3074 | * | ||
3075 | * This deadlock is avoided by perfomring async_synchronize_full() | ||
3076 | * iff module init queued any async jobs. This isn't a full | ||
3077 | * solution as it will deadlock the same if module loading from | ||
3078 | * async jobs nests more than once; however, due to the various | ||
3079 | * constraints, this hack seems to be the best option for now. | ||
3080 | * Please refer to the following thread for details. | ||
3081 | * | ||
3082 | * http://thread.gmane.org/gmane.linux.kernel/1420814 | ||
3083 | */ | ||
3084 | if (current->flags & PF_USED_ASYNC) | ||
3085 | async_synchronize_full(); | ||
3063 | 3086 | ||
3064 | mutex_lock(&module_mutex); | 3087 | mutex_lock(&module_mutex); |
3065 | /* Drop initial reference. */ | 3088 | /* Drop initial reference. */ |