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

reboot: rigrate shutdown/reboot to boot cpu

We recently noticed that reboot of a 1024 cpu machine takes approx 16
minutes of just stopping the cpus. The slowdown was tracked to commit
f96972f2dc63 ("kernel/sys.c: call disable_nonboot_cpus() in
kernel_restart()").

The current implementation does all the work of hot removing the cpus
before halting the system. We are switching to just migrating to the
boot cpu and then continuing with shutdown/reboot.

This also has the effect of not breaking x86's command line parameter
for specifying the reboot cpu. Note, this code was shamelessly copied
from arch/x86/kernel/reboot.c with bits removed pertaining to the
reboot_cpu command line parameter.

Signed-off-by: Robin Holt <holt@sgi.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Cc: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Russ Anderson <rja@sgi.com>
Cc: Robin Holt <holt@sgi.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Robin Holt and committed by
Linus Torvalds
cf7df378 16e53dbf

+26 -3
+26 -3
kernel/sys.c
··· 362 362 } 363 363 EXPORT_SYMBOL(unregister_reboot_notifier); 364 364 365 + /* Add backwards compatibility for stable trees. */ 366 + #ifndef PF_NO_SETAFFINITY 367 + #define PF_NO_SETAFFINITY PF_THREAD_BOUND 368 + #endif 369 + 370 + static void migrate_to_reboot_cpu(void) 371 + { 372 + /* The boot cpu is always logical cpu 0 */ 373 + int cpu = 0; 374 + 375 + cpu_hotplug_disable(); 376 + 377 + /* Make certain the cpu I'm about to reboot on is online */ 378 + if (!cpu_online(cpu)) 379 + cpu = cpumask_first(cpu_online_mask); 380 + 381 + /* Prevent races with other tasks migrating this task */ 382 + current->flags |= PF_NO_SETAFFINITY; 383 + 384 + /* Make certain I only run on the appropriate processor */ 385 + set_cpus_allowed_ptr(current, cpumask_of(cpu)); 386 + } 387 + 365 388 /** 366 389 * kernel_restart - reboot the system 367 390 * @cmd: pointer to buffer containing command to execute for restart ··· 396 373 void kernel_restart(char *cmd) 397 374 { 398 375 kernel_restart_prepare(cmd); 399 - disable_nonboot_cpus(); 376 + migrate_to_reboot_cpu(); 400 377 syscore_shutdown(); 401 378 if (!cmd) 402 379 printk(KERN_EMERG "Restarting system.\n"); ··· 423 400 void kernel_halt(void) 424 401 { 425 402 kernel_shutdown_prepare(SYSTEM_HALT); 426 - disable_nonboot_cpus(); 403 + migrate_to_reboot_cpu(); 427 404 syscore_shutdown(); 428 405 printk(KERN_EMERG "System halted.\n"); 429 406 kmsg_dump(KMSG_DUMP_HALT); ··· 442 419 kernel_shutdown_prepare(SYSTEM_POWER_OFF); 443 420 if (pm_power_off_prepare) 444 421 pm_power_off_prepare(); 445 - disable_nonboot_cpus(); 422 + migrate_to_reboot_cpu(); 446 423 syscore_shutdown(); 447 424 printk(KERN_EMERG "Power down.\n"); 448 425 kmsg_dump(KMSG_DUMP_POWEROFF);