Re: [PATCH 1/2] futex/requeue: Fix rtmutex schedule preparation for requeue PI
From: Yao Kai
Date: Mon Jul 20 2026 - 21:52:18 EST
On 7/20/2026 10:58 PM, Sebastian Andrzej Siewior wrote:
On 2026-07-20 10:40:03 [+0800], Yao Kai wrote:
I have a test but it only triggers the warning. The concern about calling
rt_mutex_pre_schedule() after the proxy waiter has been enqueued came from
audit. A generic PREEMPT_RT path could be:
rt_mutex_pre_schedule()
sched_submit_work()
blk_flush_plug()
__blk_flush_plug()
flush_plug_callbacks()
drbd_unplug()
spin_lock_irq()
rtlock_slowlock()
task_blocks_on_rt_mutex()
current->pi_blocked_on = waiter
However, I could not find a path for FUTEX_WAIT_REQUEUE_PI to enter with a
live current->plug or worker flags, so this recursion is not reachable from
this syscall.
So the suggestion is okay then?
…
Yes.
what about the following? This might compile but lacks all kind of testing.
diff --git a/kernel/futex/requeue.c b/kernel/futex/requeue.c
index 79823ad136830..42a04e6e774c4 100644
--- a/kernel/futex/requeue.c
+++ b/kernel/futex/requeue.c
@@ -865,7 +865,9 @@ int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
case Q_REQUEUE_PI_DONE:
/* Requeue completed. Current is 'pi_blocked_on' the rtmutex */
pi_mutex = &q.pi_state->pi_mutex;
+ rt_mutex_pre_schedule();
ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter);
+ rt_mutex_post_schedule();
/*
* See futex_unlock_pi()'s cleanup: comment.
This also fixes the warning in my test. I would keep rt_mutex_post_schedule()
after the proxy waiter cleanup, as futex_lock_pi() does:
But why?
Just to be consistent with the code in futex_lock_pi():
ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
cleanup:
/*
* If we failed to acquire the lock (deadlock/signal/timeout), we must
* unwind the above, however we canont lock hb->lock because
* rt_mutex already has a waiter enqueued and hb->lock can itself try
* and enqueue an rt_waiter through rtlock.
*
* Doing the cleanup without holding hb->lock can cause inconsistent
* state between hb and pi_state, but only in the direction of not
* seeing a waiter that is leaving.
*
* See futex_unlock_pi(), it deals with this inconsistency.
*
* There be dragons here, since we must deal with the inconsistency on
* the way out (here), it is impossible to detect/warn about the race
* the other way around (missing an incoming waiter).
*
* What could possibly go wrong...
*/
if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter))
ret = 0;
/*
* Now that the rt_waiter has been dequeued, it is safe to use
* spinlock/rtlock (which might enqueue its own rt_waiter) and fix up
* the
*/
futex_q_lockptr_lock(&q);
/*
* Waiter is unqueued.
*/
rt_mutex_post_schedule();
diff --git a/kernel/futex/requeue.c b/kernel/futex/requeue.c
index 79823ad13683..41ffc795d12c 100644
--- a/kernel/futex/requeue.c
+++ b/kernel/futex/requeue.c
@@ -865,6 +865,7 @@ int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
case Q_REQUEUE_PI_DONE:
/* Requeue completed. Current is 'pi_blocked_on' the rtmutex */
pi_mutex = &q.pi_state->pi_mutex;
+ rt_mutex_pre_schedule();
ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter);
/*
@@ -875,6 +876,7 @@ int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
futex_q_lockptr_lock(&q);
debug_rt_mutex_free_waiter(&rt_waiter);
+ rt_mutex_post_schedule();
But there is futex_q_lockptr_lock() from what I see in the context. This
one should trigger the warning if it is done as you suggest.
I don't think it would trigger the warning. At this point rt_mutex_wait_proxy_lock()
or rt_mutex_cleanup_proxy_lock() has cleared current->pi_blocked_on.
/*
* Fixup the pi_state owner and possibly acquire the lock if we
* haven't already.
Thanks,
Yao
Sebastian