Skip to content

Commit 50caf9c

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
sched: Simplify set_affinity_pending refcounts
Now that we have set_affinity_pending::stop_pending to indicate if a stopper is in progress, and we have the guarantee that if that stopper exists, it will (eventually) complete our @pending we can simplify the refcount scheme by no longer counting the stopper thread. 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]
1 parent 9e81889 commit 50caf9c

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

kernel/sched/core.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,10 @@ struct migration_arg {
18621862
struct set_affinity_pending *pending;
18631863
};
18641864

1865+
/*
1866+
* @refs: number of wait_for_completion()
1867+
* @stop_pending: is @stop_work in use
1868+
*/
18651869
struct set_affinity_pending {
18661870
refcount_t refs;
18671871
unsigned int stop_pending;
@@ -1997,10 +2001,6 @@ static int migration_cpu_stop(void *data)
19972001
if (complete)
19982002
complete_all(&pending->done);
19992003

2000-
/* For pending->{arg,stop_work} */
2001-
if (pending && refcount_dec_and_test(&pending->refs))
2002-
wake_up_var(&pending->refs);
2003-
20042004
return 0;
20052005
}
20062006

@@ -2199,12 +2199,16 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
21992199
push_task = get_task_struct(p);
22002200
}
22012201

2202+
/*
2203+
* If there are pending waiters, but no pending stop_work,
2204+
* then complete now.
2205+
*/
22022206
pending = p->migration_pending;
2203-
if (pending) {
2204-
refcount_inc(&pending->refs);
2207+
if (pending && !pending->stop_pending) {
22052208
p->migration_pending = NULL;
22062209
complete = true;
22072210
}
2211+
22082212
task_rq_unlock(rq, p, rf);
22092213

22102214
if (push_task) {
@@ -2213,7 +2217,7 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22132217
}
22142218

22152219
if (complete)
2216-
goto do_complete;
2220+
complete_all(&pending->done);
22172221

22182222
return 0;
22192223
}
@@ -2264,9 +2268,9 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22642268
if (!stop_pending)
22652269
pending->stop_pending = true;
22662270

2267-
refcount_inc(&pending->refs); /* pending->{arg,stop_work} */
22682271
if (flags & SCA_MIGRATE_ENABLE)
22692272
p->migration_flags &= ~MDF_PUSH;
2273+
22702274
task_rq_unlock(rq, p, rf);
22712275

22722276
if (!stop_pending) {
@@ -2282,27 +2286,31 @@ static int affine_move_task(struct rq *rq, struct task_struct *p, struct rq_flag
22822286
if (task_on_rq_queued(p))
22832287
rq = move_queued_task(rq, rf, p, dest_cpu);
22842288

2285-
p->migration_pending = NULL;
2286-
complete = true;
2289+
if (!pending->stop_pending) {
2290+
p->migration_pending = NULL;
2291+
complete = true;
2292+
}
22872293
}
22882294
task_rq_unlock(rq, p, rf);
22892295

2290-
do_complete:
22912296
if (complete)
22922297
complete_all(&pending->done);
22932298
}
22942299

22952300
wait_for_completion(&pending->done);
22962301

22972302
if (refcount_dec_and_test(&pending->refs))
2298-
wake_up_var(&pending->refs);
2303+
wake_up_var(&pending->refs); /* No UaF, just an address */
22992304

23002305
/*
23012306
* Block the original owner of &pending until all subsequent callers
23022307
* have seen the completion and decremented the refcount
23032308
*/
23042309
wait_var_event(&my_pending.refs, !refcount_read(&my_pending.refs));
23052310

2311+
/* ARGH */
2312+
WARN_ON_ONCE(my_pending.stop_pending);
2313+
23062314
return 0;
23072315
}
23082316

0 commit comments

Comments
 (0)