Merge branch 'for-5.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq

Pull workqueue fixes from Tejun Heo:
 "One patch to add a missing __printf annotation and the other to enable
  deferred printing for debug dumps to avoid deadlocks when triggered
  from some contexts (e.g. console drivers)"

* 'for-5.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
  workqueue: fix state-dump console deadlock
  workqueue: annotate alloc_workqueue() as printf
This commit is contained in:
Linus Torvalds 2021-10-11 16:59:49 -07:00
Родитель 1986c10acc 57116ce17b
Коммит 0a5d6c641b
2 изменённых файлов: 18 добавлений и 5 удалений

Просмотреть файл

@ -399,9 +399,8 @@ extern struct workqueue_struct *system_freezable_power_efficient_wq;
* RETURNS: * RETURNS:
* Pointer to the allocated workqueue on success, %NULL on failure. * Pointer to the allocated workqueue on success, %NULL on failure.
*/ */
struct workqueue_struct *alloc_workqueue(const char *fmt, __printf(1, 4) struct workqueue_struct *
unsigned int flags, alloc_workqueue(const char *fmt, unsigned int flags, int max_active, ...);
int max_active, ...);
/** /**
* alloc_ordered_workqueue - allocate an ordered workqueue * alloc_ordered_workqueue - allocate an ordered workqueue

Просмотреть файл

@ -4830,8 +4830,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->inactive_works)) if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
/*
* Defer printing to avoid deadlocks in console
* drivers that queue work while holding locks
* also taken in their write paths.
*/
printk_deferred_enter();
show_pwq(pwq); show_pwq(pwq);
printk_deferred_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.
@ -4849,7 +4857,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_deferred_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",
@ -4864,6 +4877,7 @@ void show_workqueue_state(void)
first = false; first = false;
} }
pr_cont("\n"); pr_cont("\n");
printk_deferred_exit();
next_pool: next_pool:
raw_spin_unlock_irqrestore(&pool->lock, flags); raw_spin_unlock_irqrestore(&pool->lock, flags);
/* /*