All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Håkon Bugge" <haakon.bugge@oracle.com>
To: linux-kernel@vger.kernel.org,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>, Will Deacon <will@kernel.org>,
	Boqun Feng <boqun@kernel.org>, Waiman Long <longman@redhat.com>,
	Chris Wilson <chris@chris-wilson.co.uk>
Cc: "John Stultz" <jstultz@google.com>,
	"Bradley Morgan" <include@grrlz.net>,
	"Håkon Bugge" <haakon.bugge@oracle.com>,
	"Ingo Molnar" <mingo@kernel.org>
Subject: [PATCH v2 2/2] test-ww_mutex: Fix deadlock in test_cycle_work
Date: Mon, 10 Aug 2026 18:34:31 +0200	[thread overview]
Message-ID: <20260810163433.3765919-2-haakon.bugge@oracle.com> (raw)
In-Reply-To: <20260810163433.3765919-1-haakon.bugge@oracle.com>

When running with N online CPUs, where N is fairly large, let's say
512, a deadlock may happen in test_cycle_work() when running with
N + 1 kernel threads. The reason is that the min_active is too small
in order to let N + 1 worker threads run concurrently. The following
is my analyzes. The test sets up a circular dependency with ww_mutexes
and completions:

	work[1]   completes signal[0]
	work[2]   completes signal[1]
	...
	work[511] completes signal[510]
	work[512] would complete signal[511]
	work[0]   completes signal[512]

Therefore:

	work[0..510] -> blocked in ww_mutex_lock(b_mutex)
	work[511]    -> blocked in wait_for_completion(signal[511])
	work[512]    -> inactive; test_cycle_work() has not started

Because the last worker thread has not started, worker 511 hangs
forever in wait_for_completion().

This bug produces the following splats (slightly edited for better
brevity). This for the worker threads hung in ww_mutex_lock():

 INFO: task kworker/u2066:1:13658 blocked for more than 123 seconds.
 Workqueue: test-ww_mutex test_cycle_work [test_ww_mutex]
 Call Trace:
  __schedule+0x28e/0x670
  schedule+0x27/0xa0
  schedule_preempt_disabled+0x15/0x30
  __ww_mutex_lock.constprop.0+0x841/0xe00
  test_cycle_work+0x9d/0x150 [test_ww_mutex]
  process_one_work+0x196/0x370
  worker_thread+0x1af/0x320
  kthread+0xe3/0x120
  ret_from_fork+0x19e/0x260
  ret_from_fork_asm+0x1a/0x30

And this for the single worker thread 511, hung in
wait_for_completion():

 Workqueue: test-ww_mutex test_cycle_work [test_ww_mutex]
 Call Trace:
  __schedule+0x28e/0x670
  schedule+0x27/0xa0
  schedule_timeout+0xac/0xf0
  __wait_for_common+0x97/0x1b0
  test_cycle_work+0x80/0x160 [test_ww_mutex]
  process_one_work+0x196/0x370
  worker_thread+0x1af/0x320
  kthread+0xe3/0x120
  ret_from_fork+0x19e/0x260
  ret_from_fork_asm+0x1a/0x30

We fix this by adjusting the wq's min_active parameter.  When
num_online_cpus() has been sampled in run_tests(), we adjust the
{min,max}_active values of the wq, to make sure both are set to ncpus
+ 1 in order to avoid the above deadlock.

Note that this fix is invariant to num_online_cpus() changing after it
has been sampled, because the RC here is the number of runnable worker
threads vs. threads created, not per se the number of online CPUs.

Also, in order to avoid exceeding WQ_MAX_ACTIVE, we create cycle_ncpus
and clamp it. We do not want to change ncpus for the other tests,
not affected by this bug.

Fixes: d1b42b800e5d ("locking/ww_mutex: Add kselftests for resolving ww_mutex cyclic deadlocks")
Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
Reviewed-by: Bradley Morgan <include@grrlz.net>

---

v1 -> v2:
      * Added Bradley's r-b
      * Reworded comment in run_tests()
---
 kernel/locking/test-ww_mutex.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 47e016a4f4fea..e11f6b869b4d4 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -676,6 +676,7 @@ static int stress(struct ww_class *class, int nlocks, int nthreads, unsigned int
 static int run_tests(struct ww_class *class)
 {
 	int ncpus = num_online_cpus();
+	int cycle_ncpus = min_t(int, ncpus, WQ_MAX_ACTIVE - 1);
 	int ret, i;
 
 	ret = test_mutex(class);
@@ -696,7 +697,17 @@ static int run_tests(struct ww_class *class)
 			return ret;
 	}
 
-	ret = test_cycle(class, ncpus);
+	/*
+	 * test_cycle_work() has a linear dependency which requires
+	 * all kernel threads to be run-able at once. With N CPUs and
+	 * N + 1 worker threads, deadlock may happen. Hence, adjust
+	 * min_active. Raise max first, min_active is clamped to it.
+	 * Cap N so that N + 1 doesn't exceed WQ_MAX_ACTIVE.
+	 */
+	workqueue_set_max_active(wq, cycle_ncpus + 1);
+	workqueue_set_min_active(wq, cycle_ncpus + 1);
+
+	ret = test_cycle(class, cycle_ncpus);
 	if (ret)
 		return ret;
 
-- 
2.43.5


  reply	other threads:[~2026-08-10 16:35 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-10 16:34 [PATCH v2 1/2] workqueue: Add missing EXPORT_SYMBOL_GPL for workqueue_set_min_active Håkon Bugge
2026-08-10 16:34 ` Håkon Bugge [this message]
2026-08-10 16:45   ` [PATCH v2 2/2] test-ww_mutex: Fix deadlock in test_cycle_work Bradley Morgan
2026-08-10 16:36 ` [PATCH v2 1/2] workqueue: Add missing EXPORT_SYMBOL_GPL for workqueue_set_min_active Bradley Morgan
2026-08-10 19:00 ` Tejun Heo
2026-08-10 19:05   ` Bradley Morgan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260810163433.3765919-2-haakon.bugge@oracle.com \
    --to=haakon.bugge@oracle.com \
    --cc=boqun@kernel.org \
    --cc=chris@chris-wilson.co.uk \
    --cc=include@grrlz.net \
    --cc=jstultz@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mingo@kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.