During a cgroup migration, cpuset_can_attach() iterates over the provided taskset. If a task within the batch is a deadline (DL) task, the destination cpuset's DL metrics (i.e., nr_migrate_dl_tasks and sum_migrate_dl_bw) are appropriately incremented. However, if a subsequent task in the same migration batch fails the task_can_attach() check, the loop aborts and jumps directly to out_unlock. Consequently, any DL metrics accumulated from previously processed tasks in the batch remain permanently inflated in the destination cpuset. Because the migration is subsequently aborted by the cgroup core, cpuset_cancel_attach() is never invoked to unwind these specific increments. This behaviour results in a permanent leak of deadline bandwidth, which incorrectly restricts the admission control capacity of the destination cpuset. To resolve this, introduce an out_unlock_reset failure path that conditionally invokes reset_migrate_dl_data(). This guarantees that if a batch migration is aborted for any reason, the pending DL metrics are safely reset before returning the error. Fixes: 0a67b847e1f06 ("cpuset: Allow setscheduler regardless of manipulated task") Cc: stable@vger.kernel.org Signed-off-by: Aaron Tomlin --- kernel/cgroup/cpuset.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index e3a081a07c6d..b8022f6e2a35 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -3029,12 +3029,12 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) cgroup_taskset_for_each(task, css, tset) { ret = task_can_attach(task); if (ret) - goto out_unlock; + goto out_unlock_reset; if (setsched_check) { ret = security_task_setscheduler(task); if (ret) - goto out_unlock; + goto out_unlock_reset; } if (dl_task(task)) { @@ -3070,6 +3070,11 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) * changes which zero cpus/mems_allowed. */ cs->attach_in_progress++; + goto out_unlock; + +out_unlock_reset: + if (cs->nr_migrate_dl_tasks) + reset_migrate_dl_data(cs); out_unlock: mutex_unlock(&cpuset_mutex); return ret; -- 2.51.0