Skip to content

Commit c8b328d

Browse files
Valentin Schneiderrostedt
authored andcommitted
sched: Don't defer CPU pick to migration_cpu_stop()
commit 475ea6c upstream. Will reported that the 'XXX __migrate_task() can fail' in migration_cpu_stop() can happen, and it *is* sort of a big deal. Looking at it some more, one will note there is a glaring hole in the deferred CPU selection: (w/ CONFIG_CPUSET=n, so that the affinity mask passed via taskset doesn't get AND'd with cpu_online_mask) $ taskset -pc 0-2 $PID # offline CPUs 3-4 $ taskset -pc 3-5 $PID `\ $PID may stay on 0-2 due to the cpumask_any_distribute() picking an offline CPU and __migrate_task() refusing to do anything due to cpu_is_allowed(). set_cpus_allowed_ptr() goes to some length to pick a dest_cpu that matches the right constraints vs affinity and the online/active state of the CPUs. Reuse that instead of discarding it in the affine_move_task() case. Fixes: 6d337ea ("sched: Fix migrate_disable() vs set_cpus_allowed_ptr()") Reported-by: Will Deacon <[email protected]> Signed-off-by: Valentin Schneider <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Paul Gortmaker <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 8a7730b commit c8b328d

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

kernel/sched/core.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,7 +1942,6 @@ static int migration_cpu_stop(void *data)
19421942
struct migration_arg *arg = data;
19431943
struct set_affinity_pending *pending = arg->pending;
19441944
struct task_struct *p = arg->task;
1945-
int dest_cpu = arg->dest_cpu;
19461945
struct rq *rq = this_rq();
19471946
bool complete = false;
19481947
struct rq_flags rf;
@@ -1975,19 +1974,15 @@ static int migration_cpu_stop(void *data)
19751974
if (p->migration_pending == pending)
19761975
p->migration_pending = NULL;
19771976
complete = true;
1978-
}
19791977

1980-
if (dest_cpu < 0) {
19811978
if (cpumask_test_cpu(task_cpu(p), &p->cpus_mask))
19821979
goto out;
1983-
1984-
dest_cpu = cpumask_any_distribute(&p->cpus_mask);
19851980
}
19861981

19871982
if (task_on_rq_queued(p))
1988-
rq = __migrate_task(rq, &rf, p, dest_cpu);
1983+
rq = __migrate_task(rq, &rf, p, arg->dest_cpu);
19891984
else
1990-
p->wake_cpu = dest_cpu;
1985+
p->wake_cpu = arg->dest_cpu;
19911986

19921987
/*
19931988
* XXX __migrate_task() can fail, at which point we might end
@@ -2266,14 +2261,23 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22662261
init_completion(&my_pending.done);
22672262
my_pending.arg = (struct migration_arg) {
22682263
.task = p,
2269-
.dest_cpu = -1, /* any */
2264+
.dest_cpu = dest_cpu,
22702265
.pending = &my_pending,
22712266
};
22722267

22732268
p->migration_pending = &my_pending;
22742269
} else {
22752270
pending = p->migration_pending;
22762271
refcount_inc(&pending->refs);
2272+
/*
2273+
* Affinity has changed, but we've already installed a
2274+
* pending. migration_cpu_stop() *must* see this, else
2275+
* we risk a completion of the pending despite having a
2276+
* task on a disallowed CPU.
2277+
*
2278+
* Serialized by p->pi_lock, so this is safe.
2279+
*/
2280+
pending->arg.dest_cpu = dest_cpu;
22772281
}
22782282
}
22792283
pending = p->migration_pending;

0 commit comments

Comments
 (0)