History

workqueue: Fix hung time report of worker pools

The workqueue watchdog prints a warning when there is no progress in a worker pool. Where the progress means that the pool started processing a pending work item. Note that it is perfectly fine to process work items much longer. The progress should be guaranteed by waking up or creating idle workers. show_one_worker_pool() prints state of non-idle worker pool. It shows a delay since the last pool->watchdog_ts. The timestamp is updated when a first pending work is queued in __queue_work(). Also it is updated when a work is dequeued for processing in worker_thread() and rescuer_thread(). The delay is misleading when there is no pending work item. In this case it shows how long the last work item is being proceed. Show zero instead. There is no stall if there is no pending work.

Petr Mladek committed 3 years ago

Commit 335a42e1 parent a8ec5881 file · +7 −3Browse files

Showing the changes to kernel/workqueue.c (1 of 1 file). Show all

Unified · Split

kernel/workqueue.c+7−3
@@ -5000,10 +5000,16 @@ static void show_one_worker_pool(struct worker_pool *pool) · 4999 unmodified lines
5000 struct worker *worker;5000 struct worker *worker;
5001 bool first = true;5001 bool first = true;
5002 unsigned long flags;5002 unsigned long flags;
5003 unsigned long hung = 0;
5003 5004
5004 raw_spin_lock_irqsave(&pool->lock, flags);5005 raw_spin_lock_irqsave(&pool->lock, flags);
5005 if (pool->nr_workers == pool->nr_idle)5006 if (pool->nr_workers == pool->nr_idle)
5006 goto next_pool;5007 goto next_pool;
5008
5009 /* How long the first pending work is waiting for a worker. */
5010 if (!list_empty(&pool->worklist))
5011 hung = jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000;
5012
5007 /*5013 /*
5008 * Defer printing to avoid deadlocks in console drivers that5014 * Defer printing to avoid deadlocks in console drivers that
5009 * queue work while holding locks also taken in their write5015 * queue work while holding locks also taken in their write
@@ -5012,9 +5018,7 @@ static void show_one_worker_pool(struct worker_pool *pool) · 2 unmodified lines
5012 printk_deferred_enter();5018 printk_deferred_enter();
5013 pr_info("pool %d:", pool->id);5019 pr_info("pool %d:", pool->id);
5014 pr_cont_pool_info(pool);5020 pr_cont_pool_info(pool);
5015 pr_cont(" hung=%us workers=%d",5021 pr_cont(" hung=%lus workers=%d", hung, pool->nr_workers);
5016 jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
5017 pool->nr_workers);
5018 if (pool->manager)5022 if (pool->manager)
5019 pr_cont(" manager: %d",5023 pr_cont(" manager: %d",
5020 task_pid_nr(pool->manager->task));5024 task_pid_nr(pool->manager->task));