The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Breno Leitao <leitao@debian.org>
To: paulmck@kernel.org, Andrew Morton <akpm@linux-foundation.org>,
	 d@ilvokhin.com
Cc: linux-kernel@vger.kernel.org,
	Peter Zijlstra <peterz@infradead.org>,
	 Ingo Molnar <mingo@kernel.org>,
	 Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	 linux-kernel@vger.kernel.org, kernel-team@meta.com,
	 Thomas Gleixner <tglx@kernel.org>,
	Breno Leitao <leitao@debian.org>
Subject: [PATCH v2 2/3] locking/csd-lock: Report how long a stuck CSD lock took to recover
Date: Mon, 10 Aug 2026 04:29:25 -0700	[thread overview]
Message-ID: <20260810-csd-stall-duration-v2-2-795083bf04a4@debian.org> (raw)
In-Reply-To: <20260810-csd-stall-duration-v2-0-795083bf04a4@debian.org>

The CSD lock debug output is a useful way to catch IPI stalls, but when
the lock finally recovers it only says that it did:

  smp: csd: CSD lock (#1) got unstuck on CPU#32, CPU#123 released the lock.

How long the target took to answer is left out, even though
csd_lock_wait_toolong() already has the timestamp the wait started from.

At Meta's fleet, that line fired 211K times in the last 24 hours, so
plenty of stalls get reported with no indication of how long they
lasted.

Print how long the lock was stuck, and, when an IPI was re-sent, how
long after that re-send the target released, as:

  smp: csd: CSD lock (#1) got unstuck on CPU#00, CPU#01 released the lock after 8000854660 ns, 3000825778 ns after the last IPI re-send.

Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Dmitry Ilvokhin <d@ilvokhin.com>
---
 kernel/smp.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/kernel/smp.c b/kernel/smp.c
index e00b8f620c5d9..c7475b3deb574 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -227,10 +227,28 @@ bool csd_lock_is_stuck(void)
 struct csd_wait_state {
 	u64 ts_start;		/* When the wait began. */
 	u64 ts_report;		/* When the last complaint was printed. */
+	u64 ts_resend;		/* When the last IPI was re-sent, 0 if never. */
 	int bug_id;
 	unsigned long nmessages;
 };
 
+/*
+ * Report a CSD lock that came back, @ts_unstuck being when the release was
+ * noticed.  Only mention the re-send delta if an IPI was actually re-sent.
+ */
+static void csd_lock_print_unstuck(struct csd_wait_state *state, int cpu, u64 ts_unstuck)
+{
+	if (state->ts_resend)
+		pr_alert("csd: CSD lock (#%d) got unstuck on CPU#%02d, CPU#%02d released the lock after %lld ns, %lld ns after the last IPI re-send.\n",
+			 state->bug_id, raw_smp_processor_id(), cpu,
+			 (s64)(ts_unstuck - state->ts_start),
+			 (s64)(ts_unstuck - state->ts_resend));
+	else
+		pr_alert("csd: CSD lock (#%d) got unstuck on CPU#%02d, CPU#%02d released the lock after %lld ns.\n",
+			 state->bug_id, raw_smp_processor_id(), cpu,
+			 (s64)(ts_unstuck - state->ts_start));
+}
+
 /*
  * Complain if too much time spent waiting.  Note that only
  * the CSD_TYPE_SYNC/ASYNC types provide the destination CPU,
@@ -249,9 +267,9 @@ static bool csd_lock_wait_toolong(call_single_data_t *csd, struct csd_wait_state
 	if (!(flags & CSD_FLAG_LOCK)) {
 		if (!unlikely(state->bug_id))
 			return true;
+		ts_now = ktime_get_mono_fast_ns();
 		cpu = csd_lock_wait_getcpu(csd);
-		pr_alert("csd: CSD lock (#%d) got unstuck on CPU#%02d, CPU#%02d released the lock.\n",
-			 state->bug_id, raw_smp_processor_id(), cpu);
+		csd_lock_print_unstuck(state, cpu, ts_now);
 		atomic_dec(&n_csd_lock_stuck);
 		return true;
 	}
@@ -309,6 +327,7 @@ static bool csd_lock_wait_toolong(call_single_data_t *csd, struct csd_wait_state
 		if (!cpu_cur_csd) {
 			pr_alert("csd: Re-sending CSD lock (#%d) IPI from CPU#%02d to CPU#%02d\n", state->bug_id, raw_smp_processor_id(), cpu);
 			arch_send_call_function_single_ipi(cpu);
+			state->ts_resend = ktime_get_mono_fast_ns();
 		}
 	}
 	if (firsttime)

-- 
2.53.0-Meta


  parent reply	other threads:[~2026-08-10 11:31 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-10 11:29 [PATCH v2 0/3] locking/csd-lock: Report how long a CSD stall lasted Breno Leitao
2026-08-10 11:29 ` [PATCH v2 1/3] locking/csd-lock: Pack csd_lock_wait_toolong() state into a struct Breno Leitao
2026-08-10 14:32   ` Dmitry Ilvokhin
2026-08-10 11:29 ` Breno Leitao [this message]
2026-08-10 11:29 ` [PATCH v2 3/3] lib/test_csd_lock: Add a module to stall a CPU on a CSD lock Breno Leitao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260810-csd-stall-duration-v2-2-795083bf04a4@debian.org \
    --to=leitao@debian.org \
    --cc=akpm@linux-foundation.org \
    --cc=bigeasy@linutronix.de \
    --cc=d@ilvokhin.com \
    --cc=kernel-team@meta.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=paulmck@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox