Skip to content

Commit 88a170e

Browse files
Peter Zijlstrarostedt
authored andcommitted
sched: Fix affine_move_task() self-concurrency
commit 9e81889 upstream. Consider: sched_setaffinity(p, X); sched_setaffinity(p, Y); Then the first will install p->migration_pending = &my_pending; and issue stop_one_cpu_nowait(pending); and the second one will read p->migration_pending and _also_ issue: stop_one_cpu_nowait(pending), the _SAME_ @pending. This causes stopper list corruption. Add set_affinity_pending::stop_pending, to indicate if a stopper is in progress. Fixes: 6d337ea ("sched: Fix migrate_disable() vs set_cpus_allowed_ptr()") Cc: [email protected] Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: Valentin Schneider <[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 4444820 commit 88a170e

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

kernel/sched/core.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,7 @@ struct migration_arg {
19001900

19011901
struct set_affinity_pending {
19021902
refcount_t refs;
1903+
unsigned int stop_pending;
19031904
struct completion done;
19041905
struct cpu_stop_work stop_work;
19051906
struct migration_arg arg;
@@ -2018,12 +2019,15 @@ static int migration_cpu_stop(void *data)
20182019
* determine is_migration_disabled() and so have to chase after
20192020
* it.
20202021
*/
2022+
WARN_ON_ONCE(!pending->stop_pending);
20212023
task_rq_unlock(rq, p, &rf);
20222024
stop_one_cpu_nowait(task_cpu(p), migration_cpu_stop,
20232025
&pending->arg, &pending->stop_work);
20242026
return 0;
20252027
}
20262028
out:
2029+
if (pending)
2030+
pending->stop_pending = false;
20272031
task_rq_unlock(rq, p, &rf);
20282032

20292033
if (complete)
@@ -2219,7 +2223,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22192223
int dest_cpu, unsigned int flags)
22202224
{
22212225
struct set_affinity_pending my_pending = { }, *pending = NULL;
2222-
bool complete = false;
2226+
bool stop_pending, complete = false;
22232227

22242228
/* Can the task run on the task's current CPU? If so, we're done */
22252229
if (cpumask_test_cpu(task_cpu(p), &p->cpus_mask)) {
@@ -2292,14 +2296,19 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22922296
* anything else we cannot do is_migration_disabled(), punt
22932297
* and have the stopper function handle it all race-free.
22942298
*/
2299+
stop_pending = pending->stop_pending;
2300+
if (!stop_pending)
2301+
pending->stop_pending = true;
22952302

22962303
refcount_inc(&pending->refs); /* pending->{arg,stop_work} */
22972304
if (flags & SCA_MIGRATE_ENABLE)
22982305
p->migration_flags &= ~MDF_PUSH;
22992306
task_rq_unlock(rq, p, rf);
23002307

2301-
stop_one_cpu_nowait(cpu_of(rq), migration_cpu_stop,
2302-
&pending->arg, &pending->stop_work);
2308+
if (!stop_pending) {
2309+
stop_one_cpu_nowait(cpu_of(rq), migration_cpu_stop,
2310+
&pending->arg, &pending->stop_work);
2311+
}
23032312

23042313
if (flags & SCA_MIGRATE_ENABLE)
23052314
return 0;

0 commit comments

Comments
 (0)