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
50005000 struct worker *worker;
50015001 bool first = true;
50025002 unsigned long flags;
5003+ unsigned long hung = 0;
50035004
50045005 raw_spin_lock_irqsave(&pool->lock, flags);
50055006 if (pool->nr_workers == pool->nr_idle)
50065007 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+
50075013 /*
50085014 * Defer printing to avoid deadlocks in console drivers that
50095015 * 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
50125018 printk_deferred_enter();
50135019 pr_info("pool %d:", pool->id);
50145020 pr_cont_pool_info(pool);
5015− pr_cont(" hung=%us workers=%d",
5016− jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
5017− pool->nr_workers);
5021+ pr_cont(" hung=%lus workers=%d", hung, pool->nr_workers);
50185022 if (pool->manager)
50195023 pr_cont(" manager: %d",
50205024 task_pid_nr(pool->manager->task));