aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/async.c3
-rw-r--r--kernel/module.c27
3 files changed, 29 insertions, 2 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 206bb089c06b..6fc8f45de4e9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1810,6 +1810,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut,
1810#define PF_MEMALLOC 0x00000800 /* Allocating memory */ 1810#define PF_MEMALLOC 0x00000800 /* Allocating memory */
1811#define PF_NPROC_EXCEEDED 0x00001000 /* set_user noticed that RLIMIT_NPROC was exceeded */ 1811#define PF_NPROC_EXCEEDED 0x00001000 /* set_user noticed that RLIMIT_NPROC was exceeded */
1812#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ 1812#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */
1813#define PF_USED_ASYNC 0x00004000 /* used async_schedule*(), used by module init */
1813#define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ 1814#define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */
1814#define PF_FROZEN 0x00010000 /* frozen for system suspend */ 1815#define PF_FROZEN 0x00010000 /* frozen for system suspend */
1815#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ 1816#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
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. */