[PATCH v2 19/21] sched: Clear cpuset_locked where the policy check retries

From: Mathieu Desnoyers

Date: Wed Nov 04 2026 - 19:47:13 EST


The retry of the policy check in __sched_setscheduler() drops
cpuset_mutex and leaves cpuset_locked saying it is held:

if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
policy = oldpolicy = -1;
task_rq_unlock(rq, p, &rf);
if (cpuset_locked) {
dl_accounting_unlock();
cpuset_unlock();
}
goto recheck;
}

sched_setparam(), and sched_setattr() with SCHED_FLAG_KEEP_POLICY, take
the policy they check from the task with no lock held, and take
cpuset_mutex for a task of SCHED_DEADLINE. A switch of that task out of
the class meanwhile makes the check retry; the second pass finds no
deadline policy to take the lock for, and the exit path unlocks a
cpuset_mutex that belongs to whoever holds it by then.
dl_accounting_mutex, added earlier in this series, goes the same way.
CONFIG_DEBUG_MUTEXES reports the unlock of a mutex the task does not
own.

Clear the flag with the lock.

Fixes: 111cd11bbc54 ("sched/cpuset: Bring back cpuset_mutex")
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx>
---
kernel/sched/syscalls.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index b1fc4fadd689..d541f4fc7252 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -654,6 +654,7 @@ int __sched_setscheduler(struct task_struct *p,
if (cpuset_locked) {
dl_accounting_unlock();
cpuset_unlock();
+ cpuset_locked = false;
}
goto recheck;
}
--
2.47.3