diff options
| -rw-r--r-- | include/linux/sched.h | 1 | ||||
| -rw-r--r-- | kernel/async.c | 3 | ||||
| -rw-r--r-- | kernel/module.c | 27 |
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. */ |
