Re: [PATCH] sched/deadline: Fix spurious -EPERM for migration-disabled tasks

From: Sebastian Andrzej Siewior

Date: Tue Nov 03 2026 - 03:17:28 EST


On 2026-11-02 14:54:19 [+0100], Andrea Parri wrote:
> sched_setattr() can refuse to make a task SCHED_DEADLINE with -EPERM,
> even though the task's affinity covers the whole root domain. A retry
> can succeed, but the error blames an affinity the task does not have.

…

> --- a/kernel/sched/syscalls.c
> +++ b/kernel/sched/syscalls.c
> @@ -628,7 +628,7 @@ int __sched_setscheduler(struct task_struct *p,
> * the entire root_domain to become SCHED_DEADLINE. We
> * will also fail if there's no bandwidth available.
> */
> - if (!cpumask_subset(span, p->cpus_ptr) ||
> + if (!cpumask_subset(span, &p->cpus_mask) ||

The task's cpus_ptr must share at least one CPU of cpus_mask. But it is
not a subset if more than one CPU is involved. So the problem is that
while it is in a migrate_disable() section after it has been scheduled
out, it will see only one CPU via ->cpus_ptr while span may have two.
That makes sense.

Reviewed-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>

Looking at sched_setaffinity(), there is dl_task_check_affinity() which
makes the same check. It is skipped for !task_has_dl_policy(). This
looks time like there is a small window in sched_setscheduler() where
the affinity check passes, the task is not yet DL, and then
sched_setaffinity() makes the affinity smaller.

> rq->rd->dl_bw.bw == 0) {
> retval = -EPERM;
> goto unlock;

Sebastian