Re: [PATCH v5] hung_task: Deduplicate identical hang reports using explicit blocker tracking

From: Aaron Tomlin

Date: Sun Jul 12 2026 - 20:09:07 EST


On Sun, Jul 12, 2026 at 04:21:00PM -0400, Aaron Tomlin wrote:
> Currently, during severe lock contention, multiple tasks can hang while
> waiting on the exact same resource. The khungtaskd kthread
> indiscriminately reports every single instance with a stack trace.
> This can roll the kernel ring buffer and prematurely exhaust the
> kernel.hung_task_warnings budget. Consequently, the kernel is left
> entirely blind to subsequent, unrelated deadlocks.
>
> To preserve the warning budget and ring buffer without sacrificing
> observability, this patch introduces a two-tier deduplication mechanism:
>
> 1. Introduces a hung_task_reported in task_struct. If a task remains
> hung across multiple check intervals, khungtaskd suppresses
> redundant stack traces for that specific task until it makes
> progress (verified via context switch counters). Furthermore, it
> is packed into an existing compiler alignment hole, consuming
> zero additional memory
>
> 2. For tasks blocked on a lock, we leverage the
> CONFIG_DETECT_HUNG_TASK_BLOCKER infrastructure. By tracking the
> exact memory address of the blocker lock in a persistent array of
> size 32, we deduplicate warning reports for tasks waiting on the
> same resource across check intervals. If the blocker is already
> tracked, the warning is suppressed and the warning budget is
> preserved
>
> 3. For duplicate tasks, we still print the single-line "INFO: task
> ..." message and trigger tracepoint trace_sched_process_hang().
> It merely skips calling sched_show_task() and
> debug_show_blocker(), printing a concise suppression notice
> instead
>
> 4. Once the hang resolves (i.e. no hung tasks are detected in a
> check round), the budget is restored to the value captured at the
> start of the hang, and the blocker array is cleared, accompanied
> by a recovery message in the ring buffer
>
> Signed-off-by: Aaron Tomlin <atomlin@xxxxxxxxxxx>
> ---
> Changes since v4:
>
> - Replaced the stack-local hashmap implementation with a persistent
> array (Petr Mladek)
>
> - Persistently track blocker addresses across scan intervals. Suppress
> warning reports and keep the sysctl_hung_task_warnings budget intact
> if the blocker is already tracked in the array (Petr Mladek)
>
> - Reset the warnings budget and clear the blocker array when the hang
> resolves (Petr Mladek)
>
> - Output a recovery message to the kernel ring buffer upon hang
> resolution
>
> - Linked to v4: https://lore.kernel.org/lkml/20260627205733.90983-1-atomlin@xxxxxxxxxxx/

Hi Petr, Lance, Masami,

Preserving the warning budget for duplicate tasks cause continuous log spam
every sysctl_hung_task_timeout_secs. This was also reported by Sashiko [1].
The following now guards sys_info() execution using a new did_report local
variable:

[1]: https://sashiko.dev/#/patchset/20260712202100.123934-1-atomlin%40atomlin.com

diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 17c285e83bb7..6bb2b26693a1 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -335,6 +335,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
unsigned long si_mask = hung_task_si_mask;
unsigned int skip_show_task;
bool scan_completed = false;
+ bool did_report = false;
#ifdef CONFIG_DETECT_HUNG_TASK_BLOCKER
unsigned long blocker;
static int warnings_reset_value;
@@ -406,9 +407,13 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
}
#endif

- hung_task_info(t, timeout, this_round_count,
- skip_show_task);
- t->hung_task_reported = 1;
+ if (!t->hung_task_reported) {
+ hung_task_info(t, timeout, this_round_count,
+ skip_show_task);
+ t->hung_task_reported = 1;
+ if (!skip_show_task)
+ did_report = true;
+ }
}
}
scan_completed = true;
@@ -450,7 +455,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
}
#endif

- if (need_warning || hung_task_call_panic) {
+ if ((need_warning && did_report) || hung_task_call_panic) {
si_mask |= SYS_INFO_LOCKS;

if (sysctl_hung_task_all_cpu_backtrace)


--
Aaron Tomlin