From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-170.mta0.migadu.com (out-170.mta0.migadu.com [91.218.175.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E242B305968 for ; Tue, 4 Aug 2026 04:23:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.170 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785817397; cv=none; b=BsL9RpXVTgKXCrCv4aaLceYkJVJZu2S0/L7iEmffM08pPLpMnz+dlpt5wOtfbLfou21AgD5/mSeGllkG/wzkgVspXNI9zbqt8JsJxGpEDt5JUc/ngo97yt5CaZBJQaG8WtQUYrn9Ytu2GOEQLmm7+CiYRkNpVjj8iIte1zfG42s= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785817397; c=relaxed/simple; bh=fLgK82VyeFPXxYaZNym6I/tiHTEQo4ojYIT1VEk7Cdo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=k7f1pKTt7MOx2MhS7Ar5gSu/A3DkJ3kdDlM8mpG9YJVQeQDBjg0QweKQ7ye9JfCH9b4kNOo0N4/7Z1oATtejVNONCwgZ4+CAQ8mF1MkqAihqfBzlhFl3rp9IQc1RO3Pev+7oX6HTNrhEQ6M1REq97GpUU9EBxrBWzWU1utRYDZc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=a/JZPqQ2; arc=none smtp.client-ip=91.218.175.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="a/JZPqQ2" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1785813529; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ISfZXBzwEbFle4s3PI1qrPuqActYcZMw5VV9QJd9h8o=; b=a/JZPqQ2C6akm0bzpAuN7YP2O/+wSJHRl7sPg+tmzz/IFhIXi9rJBs7zqtLcgLs+ps+FPk 1kOWUBNIo2YiiAI/8pupard7T8bKIsdkEURtr9AdyXKRhAfsra5qIeVVZnLVcsos5MKYEJ uaCDopHWhXEl2lmnnyA9cf/WGV+FT28= From: Lance Yang To: atomlin@atomlin.com Cc: akpm@linux-foundation.org, mhiramat@kernel.org, pmladek@suse.com, linux-kernel@vger.kernel.org, david.laight.linux@gmail.com, neelx@suse.com, sean@ashe.io, chjohnst@gmail.com, steve@abita.co, mproche@gmail.com, nick.lange@gmail.com, Lance Yang Subject: Re: [PATCH 1/2] hung_task: Reset warning budget when problem gets resolved Date: Tue, 4 Aug 2026 11:18:39 +0800 Message-Id: <20260804031839.82839-1-lance.yang@linux.dev> In-Reply-To: <20260804001542.249639-2-atomlin@atomlin.com> References: <20260804001542.249639-2-atomlin@atomlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT On Mon, Aug 03, 2026 at 08:15:41PM -0400, Aaron Tomlin wrote: >From: Petr Mladek > >sysctl_hung_task_warnings counts how many hung tasks are reported. >The watchdog does not report anything once the limit is reached. >Currently, this budget is decremented permanently, meaning the kernel is >left blind to subsequent hung tasks even after the original issue resolves. > >Keep the global sysctl_hung_task_warnings intact, and instead decrement >a copy (hung_task_warnings_printed) when warnings are printed. Reset >the copy back to the configured sysctl_hung_task_warnings limit once the >problem on the system gets resolved and check_hung_uninterruptible_tasks() >detects no hung tasks in a check interval. > >Also keep the copy updated when the global sysctl_hung_task_warnings >value is updated via sysctl, and update documentation to reflect >the new behavior. > >Assisted-by: gemini-3.5-flash >Signed-off-by: Petr Mladek >--- > Documentation/admin-guide/sysctl/kernel.rst | 6 ++-- > kernel/hung_task.c | 34 ++++++++++++++++----- > 2 files changed, 31 insertions(+), 9 deletions(-) > >diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst >index c6994e55d141..eaa1d837c739 100644 >--- a/Documentation/admin-guide/sysctl/kernel.rst >+++ b/Documentation/admin-guide/sysctl/kernel.rst >@@ -459,8 +459,10 @@ hung_task_warnings > ================== > > The maximum number of warnings to report. During a check interval >-if a hung task is detected, this value is decreased by 1. >-When this value reaches 0, no more warnings will be reported. >+if a hung task is detected, the internal warning budget is decreased by 1. >+When this budget reaches 0, no more warnings will be reported. >+The warning budget is reset back to the configured limit when the problem on the >+system gets resolved and no hung task is found. Maybe just go with this? " The maximum number of warnings to report. During a check interval if a hung task is detected, the internal warning budget is decreased by 1. When this budget reaches 0, no more detailed warnings will be reported. The warning budget is reset to the configured limit when no hung task is found. " > This file shows up if ``CONFIG_DETECT_HUNG_TASK`` is enabled. > > -1: report an infinite number of warnings. >diff --git a/kernel/hung_task.c b/kernel/hung_task.c >index 6fcc94ce4ca9..4e1fb0db79d1 100644 >--- a/kernel/hung_task.c >+++ b/kernel/hung_task.c >@@ -59,6 +59,8 @@ static unsigned long __read_mostly sysctl_hung_task_check_interval_secs; > > static int __read_mostly sysctl_hung_task_warnings = 10; > >+static int hung_task_warnings_printed = 10; >+ > static int __read_mostly did_panic; > static bool hung_task_call_panic; > >@@ -247,9 +249,9 @@ static void hung_task_info(struct task_struct *t, unsigned long timeout, > * CONFIG_DEFAULT_HUNG_TASK_TIMEOUT. Therefore, complain > * accordingly > */ >- if (sysctl_hung_task_warnings || hung_task_call_panic) { >- if (sysctl_hung_task_warnings > 0) >- sysctl_hung_task_warnings--; >+ if (hung_task_warnings_printed || hung_task_call_panic) { >+ if (hung_task_warnings_printed > 0) >+ hung_task_warnings_printed--; > pr_err("INFO: task %s:%d blocked%s for more than %ld seconds.\n", > t->comm, t->pid, t->in_iowait ? " in I/O wait" : "", > (jiffies - t->last_switch_time) / HZ); >@@ -264,7 +266,7 @@ static void hung_task_info(struct task_struct *t, unsigned long timeout, > sched_show_task(t); > debug_show_blocker(t, timeout); > >- if (!sysctl_hung_task_warnings) >+ if (!hung_task_warnings_printed) > pr_info("Future hung task reports are suppressed, see sysctl kernel.hung_task_warnings\n"); > } > >@@ -304,7 +306,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout) > unsigned long last_break = jiffies; > struct task_struct *g, *t; > unsigned long this_round_count; >- int need_warning = sysctl_hung_task_warnings; >+ int need_warning = hung_task_warnings_printed; > unsigned long si_mask = hung_task_si_mask; > > /* >@@ -340,8 +342,10 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout) > unlock: > rcu_read_unlock(); > >- if (!this_round_count) >+ if (!this_round_count) { Hmm, should max_count, or more generally scan completion, be part of this condition too? Maybe not, since a limited scan is already allowed to miss tasks ... If max_count stopped us early, we’d reset the budget even though a hung task may still be later in the list ... I probably wouldn’t change it. Just wanted to throw the question out here. >+ hung_task_warnings_printed = sysctl_hung_task_warnings; > return; >+ } > > if (need_warning || hung_task_call_panic) { > si_mask |= SYS_INFO_LOCKS; >@@ -425,6 +429,22 @@ static int proc_dohung_task_timeout_secs(const struct ctl_table *table, int writ > return ret; > } > >+static int proc_dohung_task_warnings(const struct ctl_table *table, int write, >+ void *buffer, >+ size_t *lenp, loff_t *ppos) >+{ >+ int ret; >+ >+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); >+ >+ if (ret || !write) >+ return ret; >+ >+ hung_task_warnings_printed = sysctl_hung_task_warnings; >+ >+ return 0; >+} >+ > /* > * This is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs > * and hung_task_check_interval_secs >@@ -480,7 +500,7 @@ static const struct ctl_table hung_task_sysctls[] = { > .data = &sysctl_hung_task_warnings, > .maxlen = sizeof(int), > .mode = 0644, >- .proc_handler = proc_dointvec_minmax, >+ .proc_handler = proc_dohung_task_warnings, > .extra1 = SYSCTL_NEG_ONE, > }, > { >-- Apart from that, LGTM. Reviewed-by: Lance Yang Tested-by: Lance Yang Nice and simple ;) Thanks for carrying this forward! Cheers, Lance