Re: [PATCH] sched/deadline: Fix spurious -EPERM for migration-disabled tasks
From: Andrea Parri
Date: Tue Nov 03 2026 - 13:11:24 EST
On Tue, Nov 03, 2026 at 09:11:49AM +0100, Sebastian Andrzej Siewior wrote:
[...]
> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Thanks!
> 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.
Agreed. __sched_setaffinity() calls dl_task_check_affinity() before
taking task_rq_lock(), which only __set_cpus_allowed_ptr() takes later,
whereas __sched_setscheduler() runs the admission check and switches the
policy under a single task_rq_lock(). So setaffinity can see a non-DL
task, setscheduler then admits it against the old, wide cpus_mask, and
setaffinity finally narrows it.
The window may be wider than it looks, too: it includes setaffinity
waiting for task_rq_lock() while setscheduler holds it, so the two only
need to overlap.
That's independent of this patch: the same happens with p->cpus_ptr.
restrict_cpus_allowed_ptr() already does its DL check under
task_rq_lock(), so doing the same in the setaffinity path looks like
the way to close it. One thing to keep in mind there: when
__sched_setaffinity() races with a cpuset update, it calls
__set_cpus_allowed_ptr() again to reset the task to the cpuset's mask.
That second call should probably stay unchecked, as it is today, since
cpuset_update_tasks_cpumask() narrows DL tasks without a check anyway;
refusing it would leave the task allowed on CPUs outside its cpuset.
I'll follow up on this separately.
Thanks,
Andrea