[tip: sched/urgent] sched: Reject SCHED_FLAG_KEEP_PARAMS when it would change scheduling class
From: tip-bot2 for Juri Lelli
Date: Tue Nov 03 2026 - 08:35:39 EST
The following commit has been merged into the sched/urgent branch of tip:
Commit-ID: 8a70415351ba8b4d80ce0a119a2409c1e3709855
Gitweb: https://git.kernel.org/tip/8a70415351ba8b4d80ce0a119a2409c1e3709855
Author: Juri Lelli <juri.lelli@xxxxxxxxxx>
AuthorDate: Tue, 03 Nov 2026 12:26:31 +01:00
Committer: Ingo Molnar <mingo@xxxxxxxxxx>
CommitterDate: Tue, 03 Nov 2026 14:18:05 +01:00
sched: Reject SCHED_FLAG_KEEP_PARAMS when it would change scheduling class
SCHED_FLAG_KEEP_PARAMS was introduced for uclamp (a509a7cd7974) to let
userspace adjust utilization clamping without disturbing existing
scheduling parameters. The flag skips __setscheduler_params() and the
sched_class assignment entirely.
However, when a sched_setattr() call requests a policy change that
would switch the scheduling class (e.g., SCHED_OTHER on a
SCHED_DEADLINE task) while also setting KEEP_PARAMS, the result is
contradictory: DEQUEUE_CLASS is set (because prev_class != next_class),
causing sched_change_begin() to call switched_from_dl(), but the actual
class change never happens. This leaves the task in the original class
with its bandwidth accounting corrupted.
For SCHED_DEADLINE tasks, each such call spuriously releases running_bw
and rq_bw via switched_from_dl(), leading to accounting underflow.
Reject the contradictory combination early with -EINVAL. This does not
affect the intended uclamp use case, which always pairs KEEP_PARAMS
with KEEP_POLICY (keeping the same class).
Fixes: a509a7cd7974 ("sched/uclamp: Extend sched_setattr() to support utilization clamping")
Signed-off-by: Juri Lelli <juri.lelli@xxxxxxxxxx>
Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Link: https://lore.kernel.org/all/2b5fb3f22bca6aa383be8f4781923392@xxxxxxxxxx/
Link: https://patch.msgid.link/20261103-b4-sched-dl-bw-fixes-v1-3-dd761fe005b4@xxxxxxxxxx
---
kernel/sched/syscalls.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index 45a127d..be351f8 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -675,8 +675,19 @@ change:
prev_class = p->sched_class;
next_class = __setscheduler_class(policy, newprio);
- if (prev_class != next_class)
+ if (prev_class != next_class) {
+ /*
+ * SCHED_FLAG_KEEP_PARAMS prevents the class change from
+ * actually happening (it skips __setscheduler_params and
+ * the sched_class assignment). Reject contradictory
+ * requests that ask for a class change with KEEP_PARAMS.
+ */
+ if (attr->sched_flags & SCHED_FLAG_KEEP_PARAMS) {
+ retval = -EINVAL;
+ goto unlock;
+ }
queue_flags |= DEQUEUE_CLASS;
+ }
scx_prepare_setscheduler(p, policy);