[PATCH] hung_task: Increment the global counter immediately

Petr Mladek posted 1 patch 2 days, 21 hours ago
kernel/hung_task.c | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
[PATCH] hung_task: Increment the global counter immediately
Posted by Petr Mladek 2 days, 21 hours ago
A recent change allowed to reset the global counter of hung tasks using
the sysctl interface. A potential race with the regular check has been
solved by updating the global counter only once at the end of the check.

However, the hung task check can take a significant amount of time,
particularly when task information is being dumped to slow serial
consoles. Some users monitor this global counter to trigger immediate
migration of critical containers. Delaying the increment until the
full check completes postpones these high-priority rescue operations.

Update the global counter as soon as a hung task is detected. Since
the value is read asynchronously, a relaxed atomic operation is
sufficient.

Reported-by: Lance Yang <lance.yang@linux.dev>
Closes: https://lore.kernel.org/r/f239e00f-4282-408d-b172-0f9885f4b01b@linux.dev
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
This is a followup patch for
https://lore.kernel.org/r/20260125135848.3356585-1-atomlin@atomlin.com

Note that I could not use commit IDs because the original
patchset is not in a stable tree yet. In fact, it seems
that it is not even in linux-next at the moment.

Best Regards,
Petr

 kernel/hung_task.c | 23 ++++++++---------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 350093de0535..8bc043fbe89c 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -302,15 +302,10 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
 	int max_count = sysctl_hung_task_check_count;
 	unsigned long last_break = jiffies;
 	struct task_struct *g, *t;
-	unsigned long total_count, this_round_count;
+	unsigned long this_round_count;
 	int need_warning = sysctl_hung_task_warnings;
 	unsigned long si_mask = hung_task_si_mask;
 
-	/*
-	 * The counter might get reset. Remember the initial value.
-	 * Acquire prevents reordering task checks before this point.
-	 */
-	total_count = atomic_long_read_acquire(&sysctl_hung_task_detect_count);
 	/*
 	 * If the system crashed already then all bets are off,
 	 * do not report extra hung tasks:
@@ -330,6 +325,13 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
 		}
 
 		if (task_is_hung(t, timeout)) {
+			/*
+			 * Increment the global counter so that userspace could
+			 * start migrating tasks ASAP. But count the current
+			 * round separately because userspace could reset
+			 * the global counter at any time.
+			 */
+			atomic_long_inc(&sysctl_hung_task_detect_count);
 			this_round_count++;
 			hung_task_info(t, timeout, this_round_count);
 		}
@@ -340,15 +342,6 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
 	if (!this_round_count)
 		return;
 
-	/*
-	 * Do not count this round when the global counter has been reset
-	 * during this check. Release ensures we see all hang details
-	 * recorded during the scan.
-	 */
-	atomic_long_cmpxchg_release(&sysctl_hung_task_detect_count,
-				    total_count, total_count +
-				    this_round_count);
-
 	if (need_warning || hung_task_call_panic) {
 		si_mask |= SYS_INFO_LOCKS;
 
-- 
2.52.0
Re: [PATCH] hung_task: Increment the global counter immediately
Posted by Andrew Morton 2 days, 14 hours ago
On Wed, 4 Feb 2026 12:04:54 +0100 Petr Mladek <pmladek@suse.com> wrote:

> A recent change allowed to reset the global counter of hung tasks using
> the sysctl interface. A potential race with the regular check has been
> solved by updating the global counter only once at the end of the check.
> 
> However, the hung task check can take a significant amount of time,
> particularly when task information is being dumped to slow serial
> consoles. Some users monitor this global counter to trigger immediate
> migration of critical containers. Delaying the increment until the
> full check completes postpones these high-priority rescue operations.
> 
> Update the global counter as soon as a hung task is detected. Since
> the value is read asynchronously, a relaxed atomic operation is
> sufficient.
> 
> Reported-by: Lance Yang <lance.yang@linux.dev>
> Closes: https://lore.kernel.org/r/f239e00f-4282-408d-b172-0f9885f4b01b@linux.dev
> Signed-off-by: Petr Mladek <pmladek@suse.com>
> ---
> This is a followup patch for
> https://lore.kernel.org/r/20260125135848.3356585-1-atomlin@atomlin.com
> 
> Note that I could not use commit IDs because the original
> patchset is not in a stable tree yet. In fact, it seems
> that it is not even in linux-next at the moment.

Yes, I've gone into "fixes and trivial stuff only" mode, as we're at -rc8.

Aaron, please incorporate Petr's fix into v8 and resend towards the end
of the merge window?

Thanks.
Re: [PATCH] hung_task: Increment the global counter immediately
Posted by Aaron Tomlin 12 hours ago
On Wed, Feb 04, 2026 at 10:05:49AM -0800, Andrew Morton wrote:
> On Wed, 4 Feb 2026 12:04:54 +0100 Petr Mladek <pmladek@suse.com> wrote:
> 
> > A recent change allowed to reset the global counter of hung tasks using
> > the sysctl interface. A potential race with the regular check has been
> > solved by updating the global counter only once at the end of the check.
> > 
> > However, the hung task check can take a significant amount of time,
> > particularly when task information is being dumped to slow serial
> > consoles. Some users monitor this global counter to trigger immediate
> > migration of critical containers. Delaying the increment until the
> > full check completes postpones these high-priority rescue operations.
> > 
> > Update the global counter as soon as a hung task is detected. Since
> > the value is read asynchronously, a relaxed atomic operation is
> > sufficient.
> > 
> > Reported-by: Lance Yang <lance.yang@linux.dev>
> > Closes: https://lore.kernel.org/r/f239e00f-4282-408d-b172-0f9885f4b01b@linux.dev
> > Signed-off-by: Petr Mladek <pmladek@suse.com>
> > ---
> > This is a followup patch for
> > https://lore.kernel.org/r/20260125135848.3356585-1-atomlin@atomlin.com
> > 
> > Note that I could not use commit IDs because the original
> > patchset is not in a stable tree yet. In fact, it seems
> > that it is not even in linux-next at the moment.
> 
> Yes, I've gone into "fixes and trivial stuff only" mode, as we're at -rc8.
> 
> Aaron, please incorporate Petr's fix into v8 and resend towards the end
> of the merge window?
> 
> Thanks.

Hi Andrew,

Absolutely.

Kind regards,
-- 
Aaron Tomlin
Re: [PATCH] hung_task: Increment the global counter immediately
Posted by Lance Yang 2 hours ago

On 2026/2/7 04:54, Aaron Tomlin wrote:
> On Wed, Feb 04, 2026 at 10:05:49AM -0800, Andrew Morton wrote:
>> On Wed, 4 Feb 2026 12:04:54 +0100 Petr Mladek <pmladek@suse.com> wrote:
>>
>>> A recent change allowed to reset the global counter of hung tasks using
>>> the sysctl interface. A potential race with the regular check has been
>>> solved by updating the global counter only once at the end of the check.
>>>
>>> However, the hung task check can take a significant amount of time,
>>> particularly when task information is being dumped to slow serial
>>> consoles. Some users monitor this global counter to trigger immediate
>>> migration of critical containers. Delaying the increment until the
>>> full check completes postpones these high-priority rescue operations.
>>>
>>> Update the global counter as soon as a hung task is detected. Since
>>> the value is read asynchronously, a relaxed atomic operation is
>>> sufficient.
>>>
>>> Reported-by: Lance Yang <lance.yang@linux.dev>
>>> Closes: https://lore.kernel.org/r/f239e00f-4282-408d-b172-0f9885f4b01b@linux.dev
>>> Signed-off-by: Petr Mladek <pmladek@suse.com>
>>> ---
>>> This is a followup patch for
>>> https://lore.kernel.org/r/20260125135848.3356585-1-atomlin@atomlin.com
>>>
>>> Note that I could not use commit IDs because the original
>>> patchset is not in a stable tree yet. In fact, it seems
>>> that it is not even in linux-next at the moment.
>>
>> Yes, I've gone into "fixes and trivial stuff only" mode, as we're at -rc8.
>>
>> Aaron, please incorporate Petr's fix into v8 and resend towards the end
>> of the merge window?
>>
>> Thanks.
> 
> Hi Andrew,
> 
> Absolutely.

Don't forget to credit Petr - just saying :)
Re: [PATCH] hung_task: Increment the global counter immediately
Posted by Aaron Tomlin 2 days, 18 hours ago
On Wed, Feb 04, 2026 at 12:04:54PM +0100, Petr Mladek wrote:
> A recent change allowed to reset the global counter of hung tasks using
> the sysctl interface. A potential race with the regular check has been
> solved by updating the global counter only once at the end of the check.
> 
> However, the hung task check can take a significant amount of time,
> particularly when task information is being dumped to slow serial
> consoles. Some users monitor this global counter to trigger immediate
> migration of critical containers. Delaying the increment until the
> full check completes postpones these high-priority rescue operations.
> 
> Update the global counter as soon as a hung task is detected. Since
> the value is read asynchronously, a relaxed atomic operation is
> sufficient.
> 
> Reported-by: Lance Yang <lance.yang@linux.dev>
> Closes: https://lore.kernel.org/r/f239e00f-4282-408d-b172-0f9885f4b01b@linux.dev
> Signed-off-by: Petr Mladek <pmladek@suse.com>
> ---
> This is a followup patch for
> https://lore.kernel.org/r/20260125135848.3356585-1-atomlin@atomlin.com
> 
> Note that I could not use commit IDs because the original
> patchset is not in a stable tree yet. In fact, it seems
> that it is not even in linux-next at the moment.
> 
> Best Regards,
> Petr
> 
>  kernel/hung_task.c | 23 ++++++++---------------
>  1 file changed, 8 insertions(+), 15 deletions(-)
> 
> diff --git a/kernel/hung_task.c b/kernel/hung_task.c
> index 350093de0535..8bc043fbe89c 100644
> --- a/kernel/hung_task.c
> +++ b/kernel/hung_task.c
> @@ -302,15 +302,10 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
>  	int max_count = sysctl_hung_task_check_count;
>  	unsigned long last_break = jiffies;
>  	struct task_struct *g, *t;
> -	unsigned long total_count, this_round_count;
> +	unsigned long this_round_count;
>  	int need_warning = sysctl_hung_task_warnings;
>  	unsigned long si_mask = hung_task_si_mask;
>  
> -	/*
> -	 * The counter might get reset. Remember the initial value.
> -	 * Acquire prevents reordering task checks before this point.
> -	 */
> -	total_count = atomic_long_read_acquire(&sysctl_hung_task_detect_count);
>  	/*
>  	 * If the system crashed already then all bets are off,
>  	 * do not report extra hung tasks:
> @@ -330,6 +325,13 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
>  		}
>  
>  		if (task_is_hung(t, timeout)) {
> +			/*
> +			 * Increment the global counter so that userspace could
> +			 * start migrating tasks ASAP. But count the current
> +			 * round separately because userspace could reset
> +			 * the global counter at any time.
> +			 */
> +			atomic_long_inc(&sysctl_hung_task_detect_count);
>  			this_round_count++;
>  			hung_task_info(t, timeout, this_round_count);
>  		}
> @@ -340,15 +342,6 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
>  	if (!this_round_count)
>  		return;
>  
> -	/*
> -	 * Do not count this round when the global counter has been reset
> -	 * during this check. Release ensures we see all hang details
> -	 * recorded during the scan.
> -	 */
> -	atomic_long_cmpxchg_release(&sysctl_hung_task_detect_count,
> -				    total_count, total_count +
> -				    this_round_count);
> -
>  	if (need_warning || hung_task_call_panic) {
>  		si_mask |= SYS_INFO_LOCKS;
>  
> -- 
> 2.52.0
> 

Agreed.
This is correct given the architectural shift from "Batched" to "Immediate"
updates.

Reviewed-by: Aaron Tomlin <atomlin@atomlin.com>

-- 
Aaron Tomlin
Re: [PATCH] hung_task: Increment the global counter immediately
Posted by Lance Yang 2 days, 21 hours ago

On 2026/2/4 19:04, Petr Mladek wrote:
> A recent change allowed to reset the global counter of hung tasks using
> the sysctl interface. A potential race with the regular check has been
> solved by updating the global counter only once at the end of the check.
> 
> However, the hung task check can take a significant amount of time,
> particularly when task information is being dumped to slow serial
> consoles. Some users monitor this global counter to trigger immediate
> migration of critical containers. Delaying the increment until the
> full check completes postpones these high-priority rescue operations.
> 
> Update the global counter as soon as a hung task is detected. Since
> the value is read asynchronously, a relaxed atomic operation is
> sufficient.
> 
> Reported-by: Lance Yang <lance.yang@linux.dev>
> Closes: https://lore.kernel.org/r/f239e00f-4282-408d-b172-0f9885f4b01b@linux.dev
> Signed-off-by: Petr Mladek <pmladek@suse.com>
> ---

Cool! Looks good to me:

Reviewed-by: Lance Yang <lance.yang@linux.dev>

> This is a followup patch for
> https://lore.kernel.org/r/20260125135848.3356585-1-atomlin@atomlin.com
> 
> Note that I could not use commit IDs because the original
> patchset is not in a stable tree yet. In fact, it seems
> that it is not even in linux-next at the moment.
> 
> Best Regards,
> Petr
> 
>   kernel/hung_task.c | 23 ++++++++---------------
>   1 file changed, 8 insertions(+), 15 deletions(-)
> 
> diff --git a/kernel/hung_task.c b/kernel/hung_task.c
> index 350093de0535..8bc043fbe89c 100644
> --- a/kernel/hung_task.c
> +++ b/kernel/hung_task.c
> @@ -302,15 +302,10 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
>   	int max_count = sysctl_hung_task_check_count;
>   	unsigned long last_break = jiffies;
>   	struct task_struct *g, *t;
> -	unsigned long total_count, this_round_count;
> +	unsigned long this_round_count;
>   	int need_warning = sysctl_hung_task_warnings;
>   	unsigned long si_mask = hung_task_si_mask;
>   
> -	/*
> -	 * The counter might get reset. Remember the initial value.
> -	 * Acquire prevents reordering task checks before this point.
> -	 */
> -	total_count = atomic_long_read_acquire(&sysctl_hung_task_detect_count);
>   	/*
>   	 * If the system crashed already then all bets are off,
>   	 * do not report extra hung tasks:
> @@ -330,6 +325,13 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
>   		}
>   
>   		if (task_is_hung(t, timeout)) {
> +			/*
> +			 * Increment the global counter so that userspace could
> +			 * start migrating tasks ASAP. But count the current
> +			 * round separately because userspace could reset
> +			 * the global counter at any time.
> +			 */
> +			atomic_long_inc(&sysctl_hung_task_detect_count);
>   			this_round_count++;
>   			hung_task_info(t, timeout, this_round_count);
>   		}
> @@ -340,15 +342,6 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
>   	if (!this_round_count)
>   		return;
>   
> -	/*
> -	 * Do not count this round when the global counter has been reset
> -	 * during this check. Release ensures we see all hang details
> -	 * recorded during the scan.
> -	 */
> -	atomic_long_cmpxchg_release(&sysctl_hung_task_detect_count,
> -				    total_count, total_count +
> -				    this_round_count);
> -
>   	if (need_warning || hung_task_call_panic) {
>   		si_mask |= SYS_INFO_LOCKS;
>