mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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®