summaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-27 10:20:22 +0100
committerTakashi Iwai <tiwai@suse.de>2013-01-27 10:20:22 +0100
commit257c2a02a8f668ea195bcb56eebbddc1af718e5e (patch)
tree27ccff43bc36d119dc3afeaf610638a56f4bf3ea /kernel/module.c
parent0712eea349d8e2b6d0e44b94a752d999319027fb (diff)
parenta8c136d2eba7b0b0c872e59eb404b1fe36504112 (diff)
Merge tag 'asoc-3.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v3.8-rc4 The usual set of driver updates, nothing too thrilling in here - one core change for the regulator bypass mode which was just not doing the right thing at all and a bunch of driver specifics.
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 250092c1d57..b10b048367e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3013,6 +3013,12 @@ static int do_init_module(struct module *mod)
{
int ret = 0;
+ /*
+ * We want to find out whether @mod uses async during init. Clear
+ * PF_USED_ASYNC. async_schedule*() will set it.
+ */
+ current->flags &= ~PF_USED_ASYNC;
+
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_COMING, mod);
@@ -3058,8 +3064,25 @@ static int do_init_module(struct module *mod)
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_LIVE, mod);
- /* We need to finish all async code before the module init sequence is done */
- async_synchronize_full();
+ /*
+ * We need to finish all async code before the module init sequence
+ * is done. This has potential to deadlock. For example, a newly
+ * detected block device can trigger request_module() of the
+ * default iosched from async probing task. Once userland helper
+ * reaches here, async_synchronize_full() will wait on the async
+ * task waiting on request_module() and deadlock.
+ *
+ * This deadlock is avoided by perfomring async_synchronize_full()
+ * iff module init queued any async jobs. This isn't a full
+ * solution as it will deadlock the same if module loading from
+ * async jobs nests more than once; however, due to the various
+ * constraints, this hack seems to be the best option for now.
+ * Please refer to the following thread for details.
+ *
+ * http://thread.gmane.org/gmane.linux.kernel/1420814
+ */
+ if (current->flags & PF_USED_ASYNC)
+ async_synchronize_full();
mutex_lock(&module_mutex);
/* Drop initial reference. */