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 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. */ | 
