| From: Dongmin Lee <ldmldm05@gmail.com> |
| Subject: kernel/reboot: explicitly notify if halt occurred instead of power off |
| Date: Sat, 4 Nov 2023 20:33:20 +0900 |
| |
| When kernel_can_power_off() returns false, and reboot has called with |
| LINUX_REBOOT_CMD_POWER_OFF, kernel_halt() will be initiated instead of |
| actual power off function. |
| |
| However, in this situation, Kernel never explicitly notifies user that |
| system halted instead of requested power off. |
| |
| Since halt and power off perform different behavior, and user initiated |
| reboot call with power off command, not halt, This could be unintended |
| behavior to user, like this: |
| |
| ~ # poweroff -f |
| [ 3.581482] reboot: System halted |
| |
| Therefore, this explicitly notifies user that poweroff is not available, |
| and halting has been occured as an alternative behavior instead: |
| |
| ~ # poweroff -f |
| [ 4.123668] reboot: Power off not available: System halted instead |
| |
| [akpm@linux-foundation.org: tweak comment text] |
| Link: https://lkml.kernel.org/r/20231104113320.72440-1-ldmldm05@gmail.com |
| Signed-off-by: Dongmin Lee <ldmldm05@gmail.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| kernel/reboot.c | 17 +++++++++++++++-- |
| 1 file changed, 15 insertions(+), 2 deletions(-) |
| |
| --- a/kernel/reboot.c~kernel-reboot-explicitly-notify-if-halt-occurred-instead-of-power-off |
| +++ a/kernel/reboot.c |
| @@ -59,6 +59,14 @@ struct sys_off_handler { |
| }; |
| |
| /* |
| + * This variable is used to indicate if a halt was initiated instead of a |
| + * reboot when the reboot call was invoked with LINUX_REBOOT_CMD_POWER_OFF, but |
| + * the system cannot be powered off. This allowes kernel_halt() to notify users |
| + * of that. |
| + */ |
| +static bool poweroff_fallback_to_halt; |
| + |
| +/* |
| * Temporary stub that prevents linkage failure while we're in process |
| * of removing all uses of legacy pm_power_off() around the kernel. |
| */ |
| @@ -297,7 +305,10 @@ void kernel_halt(void) |
| kernel_shutdown_prepare(SYSTEM_HALT); |
| migrate_to_reboot_cpu(); |
| syscore_shutdown(); |
| - pr_emerg("System halted\n"); |
| + if (poweroff_fallback_to_halt) |
| + pr_emerg("Power off not available: System halted instead\n"); |
| + else |
| + pr_emerg("System halted\n"); |
| kmsg_dump(KMSG_DUMP_SHUTDOWN); |
| machine_halt(); |
| } |
| @@ -732,8 +743,10 @@ SYSCALL_DEFINE4(reboot, int, magic1, int |
| /* Instead of trying to make the power_off code look like |
| * halt when pm_power_off is not set do it the easy way. |
| */ |
| - if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !kernel_can_power_off()) |
| + if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !kernel_can_power_off()) { |
| + poweroff_fallback_to_halt = true; |
| cmd = LINUX_REBOOT_CMD_HALT; |
| + } |
| |
| mutex_lock(&system_transition_mutex); |
| switch (cmd) { |
| _ |