From nobody Sun Oct 5 20:22:51 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 64C4328469A for ; Wed, 30 Jul 2025 09:53:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753869228; cv=none; b=d6po4slfz2xIleewxjGzsnmGeH2+1V1tzjqpoaVLEUw2pzOsk3AMHUvOA88GSCX2MjWL/pNGPpdMRAJVy2wMcpOMZ/u8cb6QZOqTzIUOGj/MnzjZdkmS7AAYOmbklrSWvC2pyl39OeHU66vW7F8k1+hmgMYVwFYb8adMrayj9+o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753869228; c=relaxed/simple; bh=CPQCteMb+OreyhViUgGbTgR10hVoo52HYT4Bi7mtTfI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=t01+xMBD5bhwN794nV+asiln5NermdNNdvw00Okoewwogn4lUPwZZBIqoN1bNl6ZhBJCyivt8W1H9SxqPyFjDJeRhXCA18r0shhG5gRrR8Fo80YyH8pj7xiSj5Na9UxaxqMD4K5wtO/OmSnVk/PxSytS3w8ARgvvXcg5n32eNpk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UMQK3fqi; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UMQK3fqi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B67E0C4CEF9; Wed, 30 Jul 2025 09:53:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1753869228; bh=CPQCteMb+OreyhViUgGbTgR10hVoo52HYT4Bi7mtTfI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UMQK3fqiwRoaASjsawAUdoJkEsVaq0PgVsmNockrHQ4pY8wpwNom7I6FgKl7PtUQy JSux4sVaODbi3Jd4WEGjiWR7/mcyV7jkU9nc3nvOJAdqN6LBEu68aLSOYADPTMUywi 1L3WJnJjxLhc8eHrXWyMPkwK6mw3+zP7Of5wqTYI3AqOTFwe8bTPDXVDezknRUJb8T xVgxtqyNOkDF+orDK5UcBui69q6gukLHYy7T0GUvgFXWxLzcigrAZPV1g0eWOVq4gH ekYajVUvppFSn+IL/hsGCpZkDELS2Dzf8M38GFwqGNK6aGyqNrUt6pElk+ndmo77Uq hEADdK7crDknA== From: "Masami Hiramatsu (Google)" To: Sergey Senozhatsky Cc: Peter Zijlstra , Ingo Molnar , Will Deacon , Andrew Morton , Boqun Feng , Waiman Long , Joel Granados , Anna Schumaker , Lance Yang , Kent Overstreet , Yongliang Gao , Steven Rostedt , Tomasz Figa , linux-kernel@vger.kernel.org Subject: [RFC PATCH] hung_task: Dump blocker task if it is not hung Date: Wed, 30 Jul 2025 18:53:42 +0900 Message-ID: <175386922226.617855.4016966678697742834.stgit@devnote2> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250730175150.af61caf3be97ef4cfbcc4da3@kernel.org> References: <20250730175150.af61caf3be97ef4cfbcc4da3@kernel.org> User-Agent: StGit/0.19 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: quoted-printable From: Masami Hiramatsu (Google) Dump the lock blocker task if it is not hung because if the blocker task is also hung, it should be dumped by the detector. This will de-duplicate the same stackdumps if the blocker task is also blocked by another task (and hung). Suggested-by: Sergey Senozhatsky Signed-off-by: Masami Hiramatsu (Google) Acked-by: Lance Yang --- kernel/hung_task.c | 86 ++++++++++++++++++++++++++++++------------------= ---- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/kernel/hung_task.c b/kernel/hung_task.c index d2432df2b905..52d72beb2233 100644 --- a/kernel/hung_task.c +++ b/kernel/hung_task.c @@ -94,9 +94,49 @@ static struct notifier_block panic_block =3D { .notifier_call =3D hung_task_panic, }; =20 +static bool task_is_hung(struct task_struct *t, unsigned long timeout) +{ + unsigned long switch_count =3D t->nvcsw + t->nivcsw; + unsigned int state; + + /* + * skip the TASK_KILLABLE tasks -- these can be killed + * skip the TASK_IDLE tasks -- those are genuinely idle + */ + state =3D READ_ONCE(t->__state); + if (!(state & TASK_UNINTERRUPTIBLE) || + (state & TASK_WAKEKILL) || + (state & TASK_NOLOAD)) + return false; + + /* + * Ensure the task is not frozen. + * Also, skip vfork and any other user process that freezer should skip. + */ + if (unlikely(READ_ONCE(t->__state) & TASK_FROZEN)) + return false; + + /* + * When a freshly created task is scheduled once, changes its state to + * TASK_UNINTERRUPTIBLE without having ever been switched out once, it + * musn't be checked. + */ + if (unlikely(!switch_count)) + return false; + + if (switch_count !=3D t->last_switch_count) { + t->last_switch_count =3D switch_count; + t->last_switch_time =3D jiffies; + return false; + } + if (time_is_after_jiffies(t->last_switch_time + timeout * HZ)) + return false; + + return true; +} =20 #ifdef CONFIG_DETECT_HUNG_TASK_BLOCKER -static void debug_show_blocker(struct task_struct *task) +static void debug_show_blocker(struct task_struct *task, unsigned long tim= eout) { struct task_struct *g, *t; unsigned long owner, blocker, blocker_type; @@ -153,41 +193,21 @@ static void debug_show_blocker(struct task_struct *ta= sk) task->comm, task->pid, t->comm, t->pid); break; } - sched_show_task(t); + /* Avoid duplicated task dump, skip if the task is also hung. */ + if (!task_is_hung(t, timeout)) + sched_show_task(t); return; } } #else -static inline void debug_show_blocker(struct task_struct *task) +static inline void debug_show_blocker(struct task_struct *task, unsigned l= ong timeout) { } #endif =20 static void check_hung_task(struct task_struct *t, unsigned long timeout) { - unsigned long switch_count =3D t->nvcsw + t->nivcsw; - - /* - * Ensure the task is not frozen. - * Also, skip vfork and any other user process that freezer should skip. - */ - if (unlikely(READ_ONCE(t->__state) & TASK_FROZEN)) - return; - - /* - * When a freshly created task is scheduled once, changes its state to - * TASK_UNINTERRUPTIBLE without having ever been switched out once, it - * musn't be checked. - */ - if (unlikely(!switch_count)) - return; - - if (switch_count !=3D t->last_switch_count) { - t->last_switch_count =3D switch_count; - t->last_switch_time =3D jiffies; - return; - } - if (time_is_after_jiffies(t->last_switch_time + timeout * HZ)) + if (!task_is_hung(t, timeout)) return; =20 /* @@ -222,7 +242,7 @@ static void check_hung_task(struct task_struct *t, unsi= gned long timeout) pr_err("\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\"" " disables this message.\n"); sched_show_task(t); - debug_show_blocker(t); + debug_show_blocker(t, timeout); hung_task_show_lock =3D true; =20 if (sysctl_hung_task_all_cpu_backtrace) @@ -278,7 +298,6 @@ static void check_hung_uninterruptible_tasks(unsigned l= ong timeout) hung_task_show_lock =3D false; rcu_read_lock(); for_each_process_thread(g, t) { - unsigned int state; =20 if (!max_count--) goto unlock; @@ -287,15 +306,8 @@ static void check_hung_uninterruptible_tasks(unsigned = long timeout) goto unlock; last_break =3D jiffies; } - /* - * skip the TASK_KILLABLE tasks -- these can be killed - * skip the TASK_IDLE tasks -- those are genuinely idle - */ - state =3D READ_ONCE(t->__state); - if ((state & TASK_UNINTERRUPTIBLE) && - !(state & TASK_WAKEKILL) && - !(state & TASK_NOLOAD)) - check_hung_task(t, timeout); + + check_hung_task(t, timeout); } unlock: rcu_read_unlock();