Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+44 -17
+44 -17
kernel/cpu.c
··· 663 663 return true; 664 664 } 665 665 666 - static int cpuhp_invoke_callback_range(bool bringup, 667 - unsigned int cpu, 668 - struct cpuhp_cpu_state *st, 669 - enum cpuhp_state target) 666 + static int __cpuhp_invoke_callback_range(bool bringup, 667 + unsigned int cpu, 668 + struct cpuhp_cpu_state *st, 669 + enum cpuhp_state target, 670 + bool nofail) 670 671 { 671 672 enum cpuhp_state state; 672 - int err = 0; 673 + int ret = 0; 673 674 674 675 while (cpuhp_next_state(bringup, &state, st, target)) { 676 + int err; 677 + 675 678 err = cpuhp_invoke_callback(cpu, state, bringup, NULL, NULL); 676 - if (err) 679 + if (!err) 680 + continue; 681 + 682 + if (nofail) { 683 + pr_warn("CPU %u %s state %s (%d) failed (%d)\n", 684 + cpu, bringup ? "UP" : "DOWN", 685 + cpuhp_get_step(st->state)->name, 686 + st->state, err); 687 + ret = -1; 688 + } else { 689 + ret = err; 677 690 break; 691 + } 678 692 } 679 693 680 - return err; 694 + return ret; 695 + } 696 + 697 + static inline int cpuhp_invoke_callback_range(bool bringup, 698 + unsigned int cpu, 699 + struct cpuhp_cpu_state *st, 700 + enum cpuhp_state target) 701 + { 702 + return __cpuhp_invoke_callback_range(bringup, cpu, st, target, false); 703 + } 704 + 705 + static inline void cpuhp_invoke_callback_range_nofail(bool bringup, 706 + unsigned int cpu, 707 + struct cpuhp_cpu_state *st, 708 + enum cpuhp_state target) 709 + { 710 + __cpuhp_invoke_callback_range(bringup, cpu, st, target, true); 681 711 } 682 712 683 713 static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st) ··· 1029 999 struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state); 1030 1000 enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE); 1031 1001 int err, cpu = smp_processor_id(); 1032 - int ret; 1033 1002 1034 1003 /* Ensure this CPU doesn't handle any more interrupts. */ 1035 1004 err = __cpu_disable(); ··· 1041 1012 */ 1042 1013 WARN_ON(st->state != (CPUHP_TEARDOWN_CPU - 1)); 1043 1014 1044 - /* Invoke the former CPU_DYING callbacks */ 1045 - ret = cpuhp_invoke_callback_range(false, cpu, st, target); 1046 - 1047 1015 /* 1048 - * DYING must not fail! 1016 + * Invoke the former CPU_DYING callbacks. DYING must not fail! 1049 1017 */ 1050 - WARN_ON_ONCE(ret); 1018 + cpuhp_invoke_callback_range_nofail(false, cpu, st, target); 1051 1019 1052 1020 /* Give up timekeeping duties */ 1053 1021 tick_handover_do_timer(); ··· 1322 1296 { 1323 1297 struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu); 1324 1298 enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE); 1325 - int ret; 1326 1299 1327 1300 rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */ 1328 1301 cpumask_set_cpu(cpu, &cpus_booted_once_mask); 1329 - ret = cpuhp_invoke_callback_range(true, cpu, st, target); 1330 1302 1331 1303 /* 1332 1304 * STARTING must not fail! 1333 1305 */ 1334 - WARN_ON_ONCE(ret); 1306 + cpuhp_invoke_callback_range_nofail(true, cpu, st, target); 1335 1307 } 1336 1308 1337 1309 /* ··· 2350 2326 2351 2327 if (st->state < target) 2352 2328 ret = cpu_up(dev->id, target); 2353 - else 2329 + else if (st->state > target) 2354 2330 ret = cpu_down(dev->id, target); 2331 + else if (WARN_ON(st->target != target)) 2332 + st->target = target; 2355 2333 out: 2356 2334 unlock_device_hotplug(); 2357 2335 return ret ? ret : count; ··· 2714 2688 cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask); 2715 2689 #endif 2716 2690 this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); 2691 + this_cpu_write(cpuhp_state.target, CPUHP_ONLINE); 2717 2692 } 2718 2693 2719 2694 /*