Skip to content

Commit 2ea46c6

Browse files
author
Peter Zijlstra
committed
cpumask/hotplug: Fix cpu_dying() state tracking
Vincent reported that for states with a NULL startup/teardown function we do not call cpuhp_invoke_callback() (because there is none) and as such we'll not update the cpu_dying() state. The stale cpu_dying() can eventually lead to triggering BUG(). Rectify this by updating cpu_dying() in the exact same places the hotplug machinery tracks its directional state, namely cpuhp_set_state() and cpuhp_reset_state(). Reported-by: Vincent Donnefort <[email protected]> Suggested-by: Vincent Donnefort <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Vincent Donnefort <[email protected]> Reviewed-by: Valentin Schneider <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 3a7956e commit 2ea46c6

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

kernel/cpu.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct cpuhp_cpu_state {
6363
bool rollback;
6464
bool single;
6565
bool bringup;
66+
int cpu;
6667
struct hlist_node *node;
6768
struct hlist_node *last;
6869
enum cpuhp_state cb_state;
@@ -160,9 +161,6 @@ static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,
160161
int (*cb)(unsigned int cpu);
161162
int ret, cnt;
162163

163-
if (cpu_dying(cpu) != !bringup)
164-
set_cpu_dying(cpu, !bringup);
165-
166164
if (st->fail == state) {
167165
st->fail = CPUHP_INVALID;
168166
return -EAGAIN;
@@ -467,20 +465,25 @@ static inline enum cpuhp_state
467465
cpuhp_set_state(struct cpuhp_cpu_state *st, enum cpuhp_state target)
468466
{
469467
enum cpuhp_state prev_state = st->state;
468+
bool bringup = st->state < target;
470469

471470
st->rollback = false;
472471
st->last = NULL;
473472

474473
st->target = target;
475474
st->single = false;
476-
st->bringup = st->state < target;
475+
st->bringup = bringup;
476+
if (cpu_dying(st->cpu) != !bringup)
477+
set_cpu_dying(st->cpu, !bringup);
477478

478479
return prev_state;
479480
}
480481

481482
static inline void
482483
cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state)
483484
{
485+
bool bringup = !st->bringup;
486+
484487
st->target = prev_state;
485488

486489
/*
@@ -503,7 +506,9 @@ cpuhp_reset_state(struct cpuhp_cpu_state *st, enum cpuhp_state prev_state)
503506
st->state++;
504507
}
505508

506-
st->bringup = !st->bringup;
509+
st->bringup = bringup;
510+
if (cpu_dying(st->cpu) != !bringup)
511+
set_cpu_dying(st->cpu, !bringup);
507512
}
508513

509514
/* Regular hotplug invocation of the AP hotplug thread */
@@ -693,6 +698,7 @@ static void cpuhp_create(unsigned int cpu)
693698

694699
init_completion(&st->done_up);
695700
init_completion(&st->done_down);
701+
st->cpu = cpu;
696702
}
697703

698704
static int cpuhp_should_run(unsigned int cpu)

0 commit comments

Comments
 (0)