diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/async.c | 3 | ||||
-rw-r--r-- | kernel/module.c | 27 |
2 files changed, 28 insertions, 2 deletions
diff --git a/kernel/async.c b/kernel/async.c index 9d3118384858..a1d585c351d6 100644 --- a/kernel/async.c +++ b/kernel/async.c | |||
@@ -196,6 +196,9 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a | |||
196 | atomic_inc(&entry_count); | 196 | atomic_inc(&entry_count); |
197 | spin_unlock_irqrestore(&async_lock, flags); | 197 | spin_unlock_irqrestore(&async_lock, flags); |
198 | 198 | ||
199 | /* mark that this task has queued an async job, used by module init */ | ||
200 | current->flags |= PF_USED_ASYNC; | ||
201 | |||
199 | /* schedule for execution */ | 202 | /* schedule for execution */ |
200 | queue_work(system_unbound_wq, &entry->work); | 203 | queue_work(system_unbound_wq, &entry->work); |
201 | 204 | ||
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. */ |