]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
test-ww_mutex: Allow test to be run (and re-run) from userland
authorJohn Stultz <jstultz@google.com>
Fri, 5 Dec 2025 01:35:11 +0000 (01:35 +0000)
committerPeter Zijlstra <peterz@infradead.org>
Thu, 18 Dec 2025 09:45:23 +0000 (10:45 +0100)
In cases where the ww_mutex test was occasionally tripping on
hard to find issues, leaving qemu in a reboot loop was my best
way to reproduce problems. These reboots however wasted time
when I just wanted to run the test-ww_mutex logic.

So tweak the test-ww_mutex test so that it can be re-triggered
via a sysfs file, so the test can be run repeatedly without
doing module loads or restarting.

This has been particularly valuable to stressing and finding
issues with the proxy-exec series.

To use, run as root:
  echo 1 > /sys/kernel/test_ww_mutex/run_tests

Signed-off-by: John Stultz <jstultz@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251205013515.759030-4-jstultz@google.com
kernel/locking/test-ww_mutex.c

index 30512b3e95c99723aa17b969af12aabe37e0ff1c..79b5e45f8d4c2101d6708d42e26158b2af442b69 100644 (file)
@@ -642,7 +642,7 @@ static int stress(struct ww_class *class, int nlocks, int nthreads, unsigned int
        return 0;
 }
 
-static int __init run_tests(struct ww_class *class)
+static int run_tests(struct ww_class *class)
 {
        int ncpus = num_online_cpus();
        int ret, i;
@@ -684,7 +684,7 @@ static int __init run_tests(struct ww_class *class)
        return 0;
 }
 
-static int __init run_test_classes(void)
+static int run_test_classes(void)
 {
        int ret;
 
@@ -703,6 +703,36 @@ static int __init run_test_classes(void)
        return 0;
 }
 
+static DEFINE_MUTEX(run_lock);
+
+static ssize_t run_tests_store(struct kobject *kobj, struct kobj_attribute *attr,
+                              const char *buf, size_t count)
+{
+       if (!mutex_trylock(&run_lock)) {
+               pr_err("Test already running\n");
+               return count;
+       }
+
+       run_test_classes();
+       mutex_unlock(&run_lock);
+
+       return count;
+}
+
+static struct kobj_attribute run_tests_attribute =
+       __ATTR(run_tests, 0664, NULL, run_tests_store);
+
+static struct attribute *attrs[] = {
+       &run_tests_attribute.attr,
+       NULL,   /* need to NULL terminate the list of attributes */
+};
+
+static struct attribute_group attr_group = {
+       .attrs = attrs,
+};
+
+static struct kobject *test_ww_mutex_kobj;
+
 static int __init test_ww_mutex_init(void)
 {
        int ret;
@@ -713,13 +743,30 @@ static int __init test_ww_mutex_init(void)
        if (!wq)
                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;
+       }
+
+       /* 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;
+       }
+
+       mutex_lock(&run_lock);
        ret = run_test_classes();
+       mutex_unlock(&run_lock);
 
        return ret;
 }
 
 static void __exit test_ww_mutex_exit(void)
 {
+       kobject_put(test_ww_mutex_kobj);
        destroy_workqueue(wq);
 }