Petr Mladek 660385
From 335a42ebb0ca8ee9997a1731aaaae6dcd704c113 Mon Sep 17 00:00:00 2001
Petr Mladek 660385
From: Petr Mladek <pmladek@suse.com>
Petr Mladek 660385
Date: Tue, 7 Mar 2023 13:53:31 +0100
Petr Mladek 660385
Subject: [PATCH] workqueue: Fix hung time report of worker pools
Petr Mladek 660385
Git-commit: 335a42ebb0ca8ee9997a1731aaaae6dcd704c113
Petr Mladek 660385
Patch-mainline: v6.4-rc1
Petr Mladek 660385
References: bsc#1211044
Petr Mladek 660385
Petr Mladek 660385
The workqueue watchdog prints a warning when there is no progress in
Petr Mladek 660385
a worker pool. Where the progress means that the pool started processing
Petr Mladek 660385
a pending work item.
Petr Mladek 660385
Petr Mladek 660385
Note that it is perfectly fine to process work items much longer.
Petr Mladek 660385
The progress should be guaranteed by waking up or creating idle
Petr Mladek 660385
workers.
Petr Mladek 660385
Petr Mladek 660385
show_one_worker_pool() prints state of non-idle worker pool. It shows
Petr Mladek 660385
a delay since the last pool->watchdog_ts.
Petr Mladek 660385
Petr Mladek 660385
The timestamp is updated when a first pending work is queued in
Petr Mladek 660385
__queue_work(). Also it is updated when a work is dequeued for
Petr Mladek 660385
processing in worker_thread() and rescuer_thread().
Petr Mladek 660385
Petr Mladek 660385
The delay is misleading when there is no pending work item. In this
Petr Mladek 660385
case it shows how long the last work item is being proceed. Show
Petr Mladek 660385
zero instead. There is no stall if there is no pending work.
Petr Mladek 660385
Petr Mladek 660385
Fixes: 82607adcf9cdf40fb7b ("workqueue: implement lockup detector")
Petr Mladek 660385
Signed-off-by: Petr Mladek <pmladek@suse.com>
Petr Mladek 660385
Signed-off-by: Tejun Heo <tj@kernel.org>
Petr Mladek 660385
Petr Mladek 660385
---
Petr Mladek 660385
 kernel/workqueue.c |   10 +++++++---
Petr Mladek 660385
 1 file changed, 7 insertions(+), 3 deletions(-)
Petr Mladek 660385
Petr Mladek 660385
--- a/kernel/workqueue.c
Petr Mladek 660385
+++ b/kernel/workqueue.c
Petr Mladek 660385
@@ -4879,16 +4879,19 @@ void show_workqueue_state(void)
Petr Mladek 660385
 	for_each_pool(pool, pi) {
Petr Mladek 660385
 		struct worker *worker;
Petr Mladek 660385
 		bool first = true;
Petr Mladek 660385
+		unsigned long hung = 0;
Petr Mladek 660385
 
Petr Mladek 660385
 		spin_lock_irqsave(&pool->lock, flags);
Petr Mladek 660385
 		if (pool->nr_workers == pool->nr_idle)
Petr Mladek 660385
 			goto next_pool;
Petr Mladek 660385
 
Petr Mladek 660385
+		/* How long the first pending work is waiting for a worker. */
Petr Mladek 660385
+		if (!list_empty(&pool->worklist))
Petr Mladek 660385
+			hung = jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000;
Petr Mladek 660385
+
Petr Mladek 660385
 		pr_info("pool %d:", pool->id);
Petr Mladek 660385
 		pr_cont_pool_info(pool);
Petr Mladek 660385
-		pr_cont(" hung=%us workers=%d",
Petr Mladek 660385
-			jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
Petr Mladek 660385
-			pool->nr_workers);
Petr Mladek 660385
+		pr_cont(" hung=%lus workers=%d", hung, pool->nr_workers);
Petr Mladek 660385
 		if (pool->manager)
Petr Mladek 660385
 			pr_cont(" manager: %d",
Petr Mladek 660385
 				task_pid_nr(pool->manager->task));