| From c819a3a6f84735142bcd375e352d7926ee22fbe5 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 22 Jan 2026 03:59:11 -0800 |
| Subject: rqspinlock: Fix TAS fallback lock entry creation |
| |
| From: Kumar Kartikeya Dwivedi <memxor@gmail.com> |
| |
| [ Upstream commit 82f3b142c99cf44c7b1e70b7720169c646b9760f ] |
| |
| The TAS fallback can be invoked directly when queued spin locks are |
| disabled, and through the slow path when paravirt is enabled for queued |
| spin locks. In the latter case, the res_spin_lock macro will attempt the |
| fast path and already hold the entry when entering the slow path. This |
| will lead to creation of extraneous entries that are not released, which |
| may cause false positives for deadlock detection. |
| |
| Fix this by always preceding invocation of the TAS fallback in every |
| case with the grabbing of the held lock entry, and add a comment to make |
| note of this. |
| |
| Fixes: c9102a68c070 ("rqspinlock: Add a test-and-set fallback") |
| Reported-by: Amery Hung <ameryhung@gmail.com> |
| Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> |
| Tested-by: Amery Hung <ameryhung@gmail.com> |
| Link: https://lore.kernel.org/r/20260122115911.3668985-1-memxor@gmail.com |
| Signed-off-by: Alexei Starovoitov <ast@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/asm-generic/rqspinlock.h | 2 +- |
| kernel/bpf/rqspinlock.c | 7 ++++--- |
| 2 files changed, 5 insertions(+), 4 deletions(-) |
| |
| diff --git a/include/asm-generic/rqspinlock.h b/include/asm-generic/rqspinlock.h |
| index 0f2dcbbfee2f0..5c5cf2f7fc395 100644 |
| --- a/include/asm-generic/rqspinlock.h |
| +++ b/include/asm-generic/rqspinlock.h |
| @@ -191,7 +191,7 @@ static __always_inline int res_spin_lock(rqspinlock_t *lock) |
| |
| #else |
| |
| -#define res_spin_lock(lock) resilient_tas_spin_lock(lock) |
| +#define res_spin_lock(lock) ({ grab_held_lock_entry(lock); resilient_tas_spin_lock(lock); }) |
| |
| #endif /* CONFIG_QUEUED_SPINLOCKS */ |
| |
| diff --git a/kernel/bpf/rqspinlock.c b/kernel/bpf/rqspinlock.c |
| index f7d0c8d4644ed..2fdfa828e3d35 100644 |
| --- a/kernel/bpf/rqspinlock.c |
| +++ b/kernel/bpf/rqspinlock.c |
| @@ -265,10 +265,11 @@ int __lockfunc resilient_tas_spin_lock(rqspinlock_t *lock) |
| |
| RES_INIT_TIMEOUT(ts); |
| /* |
| - * The fast path is not invoked for the TAS fallback, so we must grab |
| - * the deadlock detection entry here. |
| + * We are either called directly from res_spin_lock after grabbing the |
| + * deadlock detection entry when queued spinlocks are disabled, or from |
| + * resilient_queued_spin_lock_slowpath after grabbing the deadlock |
| + * detection entry. No need to obtain it here. |
| */ |
| - grab_held_lock_entry(lock); |
| |
| /* |
| * Since the waiting loop's time is dependent on the amount of |
| -- |
| 2.51.0 |
| |