A small set of updates for CPU hotplug:
- Prevent stale CPU hotplug state in the cpu_down() path which was detected by stress testing the sysfs interface - Ensure that the target CPU hotplug state for the boot CPU is CPUHP_ONLINE instead of the compile time init value CPUHP_OFFLINE. - Switch back to the original behaviour of warning when a CPU hotplug callback in the DYING/STARTING section returns an error code. Otherwise a buggy callback can leave the CPUs in an non recoverable state. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmOUtQQTHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYoXGLD/4h+BkT+76oQ6MEmOQC/uaDzM2eOTlE vuq9iMTMCiHjiBmkzrGT2yxzpOYiEvDJVEHfCBrwskI2rAHrjtx2VCk5yoYPajoI P604Qgml+PTCk0uOxy2pPenF4PpTQ+oe3UdfZxc3zz+Qirzsd2QpXaiY6KrNktIN vnEY0mnQjsCKf5V1/Ckws0lMUMrgHFnxQhEyT8Bvo5BhTHMpsx3zS4l0QwBanqSo hqiiYIja9alRcOKSf2l1XZB6XoNOVcubRV1YZ8saN0RJ8P7gBkeR/6Sk0Imwsn2P k3xdW1AOCoCbG8NnXH7g+ohP8k5AlpP59SsMVujXwTqI55NURFibv0rj5ZhQhSWa MKstICvUc6xyqHHwtriHyzqy3naKkiptEuxto9WL6WZYF+Xj/3JD0tT4pRvey18/ yxOjDqZAYHmS3cOh7m6VzOG4CwAu9p5qloZVzvqgR0G3LzMu66e7mucciG26TFPb C5mmUsb8SvW0yYr8ZOtKXwoQKMTZtAmU9L7DJEKRZ8AesKswaAASTgb+lDFXRId6 lxI2Vs8DPQXYJMtioYEKnwzmgHaPJ6VQKv7++74xZMHMpR/Mc3+Sm4iSIXkJK87o 07DwJMTUPR3E5/K6d4ERSvlLaKVNk3frsylhgsSmPbJn672jBe8HlDSU2uLsso2O 9kTe9KPikuHWEw== =7mN4 -----END PGP SIGNATURE----- Merge tag 'smp-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull CPU hotplug updates from Thomas Gleixner: "A small set of updates for CPU hotplug: - Prevent stale CPU hotplug state in the cpu_down() path which was detected by stress testing the sysfs interface - Ensure that the target CPU hotplug state for the boot CPU is CPUHP_ONLINE instead of the compile time init value CPUHP_OFFLINE. - Switch back to the original behaviour of warning when a CPU hotplug callback in the DYING/STARTING section returns an error code. Otherwise a buggy callback can leave the CPUs in an non recoverable state" * tag 'smp-core-2022-12-10' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: cpu/hotplug: Do not bail-out in DYING/STARTING sections cpu/hotplug: Set cpuhp target for boot cpu cpu/hotplug: Make target_store() a nop when target == state
This commit is contained in:
commit
08d72bd299
1 changed files with 44 additions and 17 deletions
61
kernel/cpu.c
61
kernel/cpu.c
|
@ -663,21 +663,51 @@ static bool cpuhp_next_state(bool bringup,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int cpuhp_invoke_callback_range(bool bringup,
|
||||
unsigned int cpu,
|
||||
struct cpuhp_cpu_state *st,
|
||||
enum cpuhp_state target)
|
||||
static int __cpuhp_invoke_callback_range(bool bringup,
|
||||
unsigned int cpu,
|
||||
struct cpuhp_cpu_state *st,
|
||||
enum cpuhp_state target,
|
||||
bool nofail)
|
||||
{
|
||||
enum cpuhp_state state;
|
||||
int err = 0;
|
||||
int ret = 0;
|
||||
|
||||
while (cpuhp_next_state(bringup, &state, st, target)) {
|
||||
int err;
|
||||
|
||||
err = cpuhp_invoke_callback(cpu, state, bringup, NULL, NULL);
|
||||
if (err)
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
if (nofail) {
|
||||
pr_warn("CPU %u %s state %s (%d) failed (%d)\n",
|
||||
cpu, bringup ? "UP" : "DOWN",
|
||||
cpuhp_get_step(st->state)->name,
|
||||
st->state, err);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int cpuhp_invoke_callback_range(bool bringup,
|
||||
unsigned int cpu,
|
||||
struct cpuhp_cpu_state *st,
|
||||
enum cpuhp_state target)
|
||||
{
|
||||
return __cpuhp_invoke_callback_range(bringup, cpu, st, target, false);
|
||||
}
|
||||
|
||||
static inline void cpuhp_invoke_callback_range_nofail(bool bringup,
|
||||
unsigned int cpu,
|
||||
struct cpuhp_cpu_state *st,
|
||||
enum cpuhp_state target)
|
||||
{
|
||||
__cpuhp_invoke_callback_range(bringup, cpu, st, target, true);
|
||||
}
|
||||
|
||||
static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st)
|
||||
|
@ -999,7 +1029,6 @@ static int take_cpu_down(void *_param)
|
|||
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
||||
enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE);
|
||||
int err, cpu = smp_processor_id();
|
||||
int ret;
|
||||
|
||||
/* Ensure this CPU doesn't handle any more interrupts. */
|
||||
err = __cpu_disable();
|
||||
|
@ -1012,13 +1041,10 @@ static int take_cpu_down(void *_param)
|
|||
*/
|
||||
WARN_ON(st->state != (CPUHP_TEARDOWN_CPU - 1));
|
||||
|
||||
/* Invoke the former CPU_DYING callbacks */
|
||||
ret = cpuhp_invoke_callback_range(false, cpu, st, target);
|
||||
|
||||
/*
|
||||
* DYING must not fail!
|
||||
* Invoke the former CPU_DYING callbacks. DYING must not fail!
|
||||
*/
|
||||
WARN_ON_ONCE(ret);
|
||||
cpuhp_invoke_callback_range_nofail(false, cpu, st, target);
|
||||
|
||||
/* Give up timekeeping duties */
|
||||
tick_handover_do_timer();
|
||||
|
@ -1296,16 +1322,14 @@ void notify_cpu_starting(unsigned int cpu)
|
|||
{
|
||||
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
||||
enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE);
|
||||
int ret;
|
||||
|
||||
rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */
|
||||
cpumask_set_cpu(cpu, &cpus_booted_once_mask);
|
||||
ret = cpuhp_invoke_callback_range(true, cpu, st, target);
|
||||
|
||||
/*
|
||||
* STARTING must not fail!
|
||||
*/
|
||||
WARN_ON_ONCE(ret);
|
||||
cpuhp_invoke_callback_range_nofail(true, cpu, st, target);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2326,8 +2350,10 @@ static ssize_t target_store(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
if (st->state < target)
|
||||
ret = cpu_up(dev->id, target);
|
||||
else
|
||||
else if (st->state > target)
|
||||
ret = cpu_down(dev->id, target);
|
||||
else if (WARN_ON(st->target != target))
|
||||
st->target = target;
|
||||
out:
|
||||
unlock_device_hotplug();
|
||||
return ret ? ret : count;
|
||||
|
@ -2688,6 +2714,7 @@ void __init boot_cpu_hotplug_init(void)
|
|||
cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask);
|
||||
#endif
|
||||
this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
|
||||
this_cpu_write(cpuhp_state.target, CPUHP_ONLINE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue