* [PATCH v3 0/3] test-ww_mutex: Miscellaneous fixes
@ 2026-08-04 16:31 Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 1/3] test-ww_mutex: Fix module cleanup Håkon Bugge
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Håkon Bugge @ 2026-08-04 16:31 UTC (permalink / raw)
To: linux-kernel
This series fixes:
- module cleanup
- error propagation from stress workers
- transient -EDEADLK handling in test_cycle_work()
The series is re-based on v7.2-rc6 and has been tested on a 96-CPU
x86_64 bare-metal system and a 160-CPU arm64 bare-metal system. With
the test "stress_inorder_work" disabled, both systems completed 100
iterations of tools/testing/selftests/locking/ww_mutex.sh successfully
with the self-test as a module. With the self-test as a built-in, the
systems survived:
for N in {1..100}; do
echo 1 > /sys/kernel/test_ww_mutex/run_tests
done
The main differences between the v2 contribution and this v3, is that
the last patch is removed.
Håkon Bugge (3):
test-ww_mutex: Fix module cleanup
test-ww_mutex: Report errors from stress workers
test-ww_mutex: Handle transient -EDEADLK in test_cycle_work
kernel/locking/test-ww_mutex.c | 65 +++++++++++++++++++++++++++-------
1 file changed, 52 insertions(+), 13 deletions(-)
--
2.43.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/3] test-ww_mutex: Fix module cleanup
2026-08-04 16:31 [PATCH v3 0/3] test-ww_mutex: Miscellaneous fixes Håkon Bugge
@ 2026-08-04 16:31 ` Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 2/3] test-ww_mutex: Report errors from stress workers Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 3/3] test-ww_mutex: Handle transient -EDEADLK in test_cycle_work Håkon Bugge
2 siblings, 0 replies; 5+ messages in thread
From: Håkon Bugge @ 2026-08-04 16:31 UTC (permalink / raw)
To: linux-kernel, Peter Zijlstra, Ingo Molnar, Will Deacon,
Boqun Feng, Waiman Long, Chris Wilson, John Stultz
Cc: Håkon Bugge, Ingo Molnar
When test-ww_mutex is compiled as a module, there are two bugs. One is
related to the case where the module fails to load. In that case, some
or all of the allocated objects are not released. Also, if loaded OK
and thereafter unloaded, the sysfs file is not removed.
The latter bug gives the following splat (trimmed for better brevity):
sysfs: cannot create duplicate filename '/kernel/test_ww_mutex'
dump_stack_lvl+0x5d/0x90
sysfs_warn_dup.cold+0x17/0x23
sysfs_create_dir_ns+0xe2/0x100
kobject_add_internal+0xba/0x270
kobject_add+0x95/0xd0
kobject_create_and_add+0xa3/0xd0
test_ww_mutex_init+0x90/0xff0 [test_ww_mutex]
do_one_initcall+0x5c/0x330
do_init_module+0x90/0x290
__do_sys_init_module+0x195/0x1d0
do_syscall_64+0xe8/0x550
entry_SYSCALL_64_after_hwframe+0x76/0x7e
Fixes: 2a0c11282881 ("locking/ww_mutex: Add kselftests for ww_mutex stress")
Fixes: de2c5a1523fd ("test-ww_mutex: Allow test to be run (and re-run) from userland")
Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
Acked-by: John Stultz <jstultz@google.com>
---
v1 -> v2:
* Keep the sysfs file if module is built-in even when the test
fails. This in order to be able to run the test multiple
times even in case of errors. Suggested by John Stultz
---
kernel/locking/test-ww_mutex.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 838d631544ed2..8311ff38ab683 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -734,7 +734,7 @@ static struct kobject *test_ww_mutex_kobj;
static int __init test_ww_mutex_init(void)
{
- int ret;
+ int ret = -ENOMEM;
prandom_seed_state(&rng, get_random_u64());
@@ -743,28 +743,35 @@ static int __init test_ww_mutex_init(void)
return -ENOMEM;
test_ww_mutex_kobj = kobject_create_and_add("test_ww_mutex", kernel_kobj);
- if (!test_ww_mutex_kobj) {
- destroy_workqueue(wq);
- return -ENOMEM;
- }
+ if (!test_ww_mutex_kobj)
+ goto kobj_err;
/* Create the files associated with this kobject */
ret = sysfs_create_group(test_ww_mutex_kobj, &attr_group);
- if (ret) {
- kobject_put(test_ww_mutex_kobj);
- destroy_workqueue(wq);
- return ret;
- }
+ if (ret)
+ goto sysfs_err;
mutex_lock(&run_lock);
ret = run_test_classes();
mutex_unlock(&run_lock);
+ if (!ret || IS_BUILTIN(CONFIG_WW_MUTEX_SELFTEST))
+ return 0;
+
+ sysfs_remove_group(test_ww_mutex_kobj, &attr_group);
+
+sysfs_err:
+ kobject_put(test_ww_mutex_kobj);
+
+kobj_err:
+ destroy_workqueue(wq);
+
return ret;
}
static void __exit test_ww_mutex_exit(void)
{
+ sysfs_remove_group(test_ww_mutex_kobj, &attr_group);
kobject_put(test_ww_mutex_kobj);
destroy_workqueue(wq);
}
--
2.43.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 2/3] test-ww_mutex: Report errors from stress workers
2026-08-04 16:31 [PATCH v3 0/3] test-ww_mutex: Miscellaneous fixes Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 1/3] test-ww_mutex: Fix module cleanup Håkon Bugge
@ 2026-08-04 16:31 ` Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 3/3] test-ww_mutex: Handle transient -EDEADLK in test_cycle_work Håkon Bugge
2 siblings, 0 replies; 5+ messages in thread
From: Håkon Bugge @ 2026-08-04 16:31 UTC (permalink / raw)
To: linux-kernel, Peter Zijlstra, Ingo Molnar, Will Deacon,
Boqun Feng, Waiman Long, Chris Wilson
Cc: Håkon Bugge, John Stultz, Ingo Molnar
If any of stress_one_work(), stress_reorder_work(), or
stress_inorder_work() fails, the error is not conveyed back to the
test harness function stress().
We may then see in the log:
stress (stress_inorder_work) failed with -35
Beginning ww (die) mutex selftests
All ww mutex selftests passed
Besides being a contradiction by terms, the failure to return error
from said worker functions leads to false-positive results.
We fix that by adding a *result* variable to *struct stress*, update
it in said worker functions, and finally, in stress(), scan the
*stress_array* and report the first error if any.
Fixes: 2a0c11282881 ("locking/ww_mutex: Add kselftests for ww_mutex stress")
Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
Acked-by: John Stultz <jstultz@google.com>
---
v1 -> v2:
* Added John's a-b
---
kernel/locking/test-ww_mutex.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 8311ff38ab683..5ed91f2cf30d9 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -392,6 +392,7 @@ struct stress {
struct ww_class *class;
unsigned long timeout;
int nlocks;
+ int result;
};
struct rnd_state rng;
@@ -440,6 +441,9 @@ static void stress_inorder_work(struct work_struct *work)
struct ww_mutex *locks = stress->locks;
struct ww_acquire_ctx ctx;
int *order;
+ int err;
+
+ stress->result = -ENOMEM;
order = get_random_order(nlocks);
if (!order)
@@ -447,7 +451,7 @@ static void stress_inorder_work(struct work_struct *work)
do {
int contended = -1;
- int n, err;
+ int n;
ww_acquire_init(&ctx, stress->class);
retry:
@@ -485,6 +489,7 @@ static void stress_inorder_work(struct work_struct *work)
} while (!time_after(jiffies, stress->timeout));
kfree(order);
+ stress->result = err;
}
struct reorder_lock {
@@ -501,6 +506,8 @@ static void stress_reorder_work(struct work_struct *work)
int *order;
int n, err;
+ stress->result = -ENOMEM;
+
order = get_random_order(stress->nlocks);
if (!order)
return;
@@ -545,6 +552,8 @@ static void stress_reorder_work(struct work_struct *work)
ww_acquire_fini(&ctx);
} while (!time_after(jiffies, stress->timeout));
+ stress->result = err;
+
out:
list_for_each_entry_safe(ll, ln, &locks, link)
kfree(ll);
@@ -569,6 +578,8 @@ static void stress_one_work(struct work_struct *work)
break;
}
} while (!time_after(jiffies, stress->timeout));
+
+ stress->result = err;
}
#define STRESS_INORDER BIT(0)
@@ -581,6 +592,7 @@ static int stress(struct ww_class *class, int nlocks, int nthreads, unsigned int
struct ww_mutex *locks;
struct stress *stress_array;
int n, count;
+ int res = 0;
locks = kmalloc_objs(*locks, nlocks);
if (!locks)
@@ -635,10 +647,15 @@ static int stress(struct ww_class *class, int nlocks, int nthreads, unsigned int
for (n = 0; n < nlocks; n++)
ww_mutex_destroy(&locks[n]);
+
+ /* Report the first error */
+ for (n = 0; !res && n < count; n++)
+ res = stress_array[n].result;
+
kfree(stress_array);
kfree(locks);
- return 0;
+ return res;
}
static int run_tests(struct ww_class *class)
--
2.43.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 3/3] test-ww_mutex: Handle transient -EDEADLK in test_cycle_work
2026-08-04 16:31 [PATCH v3 0/3] test-ww_mutex: Miscellaneous fixes Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 1/3] test-ww_mutex: Fix module cleanup Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 2/3] test-ww_mutex: Report errors from stress workers Håkon Bugge
@ 2026-08-04 16:31 ` Håkon Bugge
2026-08-18 8:35 ` Haakon Bugge
2 siblings, 1 reply; 5+ messages in thread
From: Håkon Bugge @ 2026-08-04 16:31 UTC (permalink / raw)
To: linux-kernel, Peter Zijlstra, Ingo Molnar, Will Deacon,
Boqun Feng, Waiman Long, Chris Wilson, Guenter Roeck
Cc: Håkon Bugge, John Stultz, Ingo Molnar
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@oracle.com>
Acked-by: John Stultz <jstultz@google.com>
---
v2 -> v3:
* Added John's a-b
* Renamed the "ok" label to "out", as suggested by John
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..47e016a4f4fea 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 out;
+
+ 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;
}
+out:
if (!err)
ww_mutex_unlock(cycle->b_mutex);
if (!erra)
--
2.43.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v3 3/3] test-ww_mutex: Handle transient -EDEADLK in test_cycle_work
2026-08-04 16:31 ` [PATCH v3 3/3] test-ww_mutex: Handle transient -EDEADLK in test_cycle_work Håkon Bugge
@ 2026-08-18 8:35 ` Haakon Bugge
0 siblings, 0 replies; 5+ messages in thread
From: Haakon Bugge @ 2026-08-18 8:35 UTC (permalink / raw)
To: linux-kernel, Peter Zijlstra, Ingo Molnar, Will Deacon,
Boqun Feng, Waiman Long, Chris Wilson, Guenter Roeck
Cc: John Stultz, Ingo Molnar
> On 4 Aug 2026, at 18:31, Håkon Bugge <Haakon.Bugge@oracle.com> wrote:
>
> 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@oracle.com>
> Acked-by: John Stultz <jstultz@google.com>
A gentle ping on the v3 of this series.
Thxs, Håkon
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-18 8:36 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-04 16:31 [PATCH v3 0/3] test-ww_mutex: Miscellaneous fixes Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 1/3] test-ww_mutex: Fix module cleanup Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 2/3] test-ww_mutex: Report errors from stress workers Håkon Bugge
2026-08-04 16:31 ` [PATCH v3 3/3] test-ww_mutex: Handle transient -EDEADLK in test_cycle_work Håkon Bugge
2026-08-18 8:35 ` Haakon Bugge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®