• Johan Hovold's avatar
    workqueue: fix state-dump console deadlock · 57116ce1
    Johan Hovold authored
    Console drivers often queue work while holding locks also taken in their
    console write paths, something which can lead to deadlocks on SMP when
    dumping workqueue state (e.g. sysrq-t or on suspend failures).
    
    For serial console drivers this could look like:
    
    	CPU0				CPU1
    	----				----
    
    	show_workqueue_state();
    	  lock(&pool->lock);		<IRQ>
    	  				  lock(&port->lock);
    					  schedule_work();
    					    lock(&pool->lock);
    	  printk();
    	    lock(console_owner);
    	    lock(&port->lock);
    
    where workqueues are, for example, used to push data to the line
    discipline, process break signals and handle modem-status changes. Line
    disciplines and serdev drivers can also queue work on write-wakeup
    notifications, etc.
    
    Reworking every console driver to avoid queuing work while holding locks
    also taken in their write paths would complicate drivers and is neither
    desirable or feasible.
    
    Instead use the deferred-printk mechanism to avoid printing while
    holding pool locks when dumping workqueue state.
    
    Note that there are a few WARN_ON() assertions in the workqueue code
    which could potentially also trigger a deadlock. Hopefully the ongoing
    printk rework will provide a general solution for this eventually.
    
    This was originally reported after a lockdep splat when executing
    sysrq-t with the imx serial driver.
    
    Fixes: 3494fc30 ("workqueue: dump workqueues on sysrq-t")
    Cc: stable@vger.kernel.org	# 4.0
    Reported-by: default avatarFabio Estevam <festevam@denx.de>
    Tested-by: default avatarFabio Estevam <festevam@denx.de>
    Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
    Reviewed-by: default avatarJohn Ogness <john.ogness@linutronix.de>
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    57116ce1
workqueue.c 168 KB