[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250107140004.2732830-14-memxor@gmail.com>
Date: Tue, 7 Jan 2025 05:59:55 -0800
From: Kumar Kartikeya Dwivedi <memxor@...il.com>
To: bpf@...r.kernel.org,
linux-kernel@...r.kernel.org
Cc: Linus Torvalds <torvalds@...ux-foundation.org>,
Peter Zijlstra <peterz@...radead.org>,
Waiman Long <llong@...hat.com>,
Alexei Starovoitov <ast@...nel.org>,
Andrii Nakryiko <andrii@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Martin KaFai Lau <martin.lau@...nel.org>,
Eduard Zingerman <eddyz87@...il.com>,
"Paul E. McKenney" <paulmck@...nel.org>,
Tejun Heo <tj@...nel.org>,
Barret Rhoden <brho@...gle.com>,
Josh Don <joshdon@...gle.com>,
Dohyun Kim <dohyunkim@...gle.com>,
kernel-team@...a.com
Subject: [PATCH bpf-next v1 13/22] rqspinlock: Add helper to print a splat on timeout or deadlock
Whenever a timeout and a deadlock occurs, we would want to print a
message to the dmesg console, including the CPU where the event
occurred, the list of locks in the held locks table, and the stack trace
of the caller, which allows determining where exactly in the slow path
the waiter timed out or detected a deadlock.
Splats are limited to atmost one per-CPU during machine uptime, and a
lock is acquired to ensure that no interleaving occurs when a concurrent
set of CPUs conflict and enter a deadlock situation and start printing
data.
Later patches will use this to inspect return value of rqspinlock API
and then report a violation if necessary.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@...il.com>
---
kernel/locking/rqspinlock.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/kernel/locking/rqspinlock.c b/kernel/locking/rqspinlock.c
index e397f91ebcf6..467336f6828e 100644
--- a/kernel/locking/rqspinlock.c
+++ b/kernel/locking/rqspinlock.c
@@ -187,6 +187,35 @@ static noinline int check_deadlock_ABBA(struct qspinlock *lock, u32 mask,
return 0;
}
+static DEFINE_PER_CPU(int, report_nest_cnt);
+static DEFINE_PER_CPU(bool, report_flag);
+static arch_spinlock_t report_lock;
+
+static void rqspinlock_report_violation(const char *s, void *lock)
+{
+ struct rqspinlock_held *rqh = this_cpu_ptr(&rqspinlock_held_locks);
+
+ if (this_cpu_inc_return(report_nest_cnt) != 1) {
+ this_cpu_dec(report_nest_cnt);
+ return;
+ }
+ if (this_cpu_read(report_flag))
+ goto end;
+ this_cpu_write(report_flag, true);
+ arch_spin_lock(&report_lock);
+
+ pr_err("CPU %d: %s", smp_processor_id(), s);
+ pr_info("Held locks: %d\n", rqh->cnt + 1);
+ pr_info("Held lock[%2d] = 0x%px\n", 0, lock);
+ for (int i = 0; i < min(RES_NR_HELD, rqh->cnt); i++)
+ pr_info("Held lock[%2d] = 0x%px\n", i + 1, rqh->locks[i]);
+ dump_stack();
+
+ arch_spin_unlock(&report_lock);
+end:
+ this_cpu_dec(report_nest_cnt);
+}
+
static noinline int check_deadlock(struct qspinlock *lock, u32 mask,
struct rqspinlock_timeout *ts)
{
--
2.43.5
Powered by blists - more mailing lists