You need to sign in or sign up before continuing.
提交 f658de5e 编写于 作者: J Johan Hovold 提交者: Zheng Zengkai

workqueue: fix state-dump console deadlock

mainline inclusion
from mainline-v5.15-rc6
commit 57116ce1
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I61CQ3

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=57116ce17b04fde2fe30f0859df69d8dbe5809f6

-------------------------------------------------

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: NFabio Estevam <festevam@denx.de>
Tested-by: NFabio Estevam <festevam@denx.de>
Signed-off-by: NJohan Hovold <johan@kernel.org>
Reviewed-by: NJohn Ogness <john.ogness@linutronix.de>
Signed-off-by: NTejun Heo <tj@kernel.org>
Signed-off-by: NWang ShaoBo <bobo.shaobowang@huawei.com>
Reviewed-by: NXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 4a6ae615
...@@ -4809,8 +4809,16 @@ void show_workqueue_state(void) ...@@ -4809,8 +4809,16 @@ void show_workqueue_state(void)
for_each_pwq(pwq, wq) { for_each_pwq(pwq, wq) {
raw_spin_lock_irqsave(&pwq->pool->lock, flags); raw_spin_lock_irqsave(&pwq->pool->lock, flags);
if (pwq->nr_active || !list_empty(&pwq->delayed_works)) if (pwq->nr_active || !list_empty(&pwq->delayed_works)) {
/*
* Defer printing to avoid deadlocks in console
* drivers that queue work while holding locks
* also taken in their write paths.
*/
printk_safe_enter();
show_pwq(pwq); show_pwq(pwq);
printk_safe_exit();
}
raw_spin_unlock_irqrestore(&pwq->pool->lock, flags); raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
/* /*
* We could be printing a lot from atomic context, e.g. * We could be printing a lot from atomic context, e.g.
...@@ -4828,7 +4836,12 @@ void show_workqueue_state(void) ...@@ -4828,7 +4836,12 @@ void show_workqueue_state(void)
raw_spin_lock_irqsave(&pool->lock, flags); raw_spin_lock_irqsave(&pool->lock, flags);
if (pool->nr_workers == pool->nr_idle) if (pool->nr_workers == pool->nr_idle)
goto next_pool; goto next_pool;
/*
* Defer printing to avoid deadlocks in console drivers that
* queue work while holding locks also taken in their write
* paths.
*/
printk_safe_enter();
pr_info("pool %d:", pool->id); pr_info("pool %d:", pool->id);
pr_cont_pool_info(pool); pr_cont_pool_info(pool);
pr_cont(" hung=%us workers=%d", pr_cont(" hung=%us workers=%d",
...@@ -4843,6 +4856,7 @@ void show_workqueue_state(void) ...@@ -4843,6 +4856,7 @@ void show_workqueue_state(void)
first = false; first = false;
} }
pr_cont("\n"); pr_cont("\n");
printk_safe_exit();
next_pool: next_pool:
raw_spin_unlock_irqrestore(&pool->lock, flags); raw_spin_unlock_irqrestore(&pool->lock, flags);
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册