[PATCH v2 3/4] test-ww_mutex: Handle transient -EDEADLK in test_cycle_work

From: Håkon Bugge

Date: Mon Jul 13 2026 - 12:39:01 EST


There is a timing issue in test_cycle_work(), in the sense that
acquiring *a_mutex* after deadlock has been detected on the *b_mutex*,
may not succeed immediately. This may lead to false negatives, which
shows up in the log as:

cyclic deadlock not resolved, ret[77/93] = -35

We re-factor the inner part test_cycle_work(), where we loop a few
times attempting to acquire the mutexes in BAAB order. If the first A
succeeds or the last B succeeds, we break out of the loop.

Fixes: d1b42b800e5d ("locking/ww_mutex: Add kselftests for resolving ww_mutex cyclic deadlocks")
Fixes: e4a02ed2aaf4 ("locking/ww_mutex: Fix runtime warning in the WW mutex selftest")
Signed-off-by: Håkon Bugge <haakon.bugge@xxxxxxxxxx>

---

v1 -> v2:
* Removed the end-less lock acquisition attempts, as that
strategy did not obey the big-rules of the WW
mutexes. Instead, re-factor the test, and loop a handful
times.
---
kernel/locking/test-ww_mutex.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 5ed91f2cf30d9..190b8ac5c5520 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -294,6 +294,8 @@ static void test_cycle_work(struct work_struct *work)
struct test_cycle *cycle = container_of(work, typeof(*cycle), work);
struct ww_acquire_ctx ctx;
int err, erra = 0;
+ const int max_attempts = 5;
+ int attempt;

ww_acquire_init_noinject(&ctx, cycle->class);
ww_mutex_lock(&cycle->a_mutex, &ctx);
@@ -302,13 +304,26 @@ static void test_cycle_work(struct work_struct *work)
wait_for_completion(&cycle->b_signal);

err = ww_mutex_lock(cycle->b_mutex, &ctx);
- if (err == -EDEADLK) {
+ if (err != -EDEADLK)
+ goto ok;
+
+ for (attempt = 0; attempt < max_attempts; ++attempt) {
err = 0;
ww_mutex_unlock(&cycle->a_mutex);
ww_mutex_lock_slow(cycle->b_mutex, &ctx);
erra = ww_mutex_lock(&cycle->a_mutex, &ctx);
+ if (erra != -EDEADLK)
+ break;
+
+ erra = 0;
+ ww_mutex_unlock(cycle->b_mutex);
+ ww_mutex_lock_slow(&cycle->a_mutex, &ctx);
+ err = ww_mutex_lock(cycle->b_mutex, &ctx);
+ if (err != -EDEADLK)
+ break;
}

+ok:
if (!err)
ww_mutex_unlock(cycle->b_mutex);
if (!erra)
--
2.43.5