X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fshutdown.c;h=0b0e0c3d476c3d10c74ce0044706adf1c291195e;hb=8e70580bb07ae46dc0b0bf377de6333540668acc;hp=558111b3d48ebbf0be1e42cc56ea2b3e199f0ddd;hpb=57371e5829a61e5ee6c9f98404dfc729d6c62608;p=elogind.git diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 558111b3d..0b0e0c3d4 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -197,31 +197,34 @@ int main(int argc, char *argv[]) { if (need_umount) { log_info("Unmounting file systems."); r = umount_all(&changed); - if (r == 0) + if (r == 0) { need_umount = false; - else if (r > 0) + log_info("All filesystems unmounted."); + } else if (r > 0) log_info("Not all file systems unmounted, %d left.", r); else log_error("Failed to unmount file systems: %s", strerror(-r)); } if (need_swapoff) { - log_info("Disabling swaps."); + log_info("Deactivating swaps."); r = swapoff_all(&changed); - if (r == 0) + if (r == 0) { need_swapoff = false; - else if (r > 0) - log_info("Not all swaps are turned off, %d left.", r); + log_info("All swaps deactivated."); + } else if (r > 0) + log_info("Not all swaps deactivated, %d left.", r); else - log_error("Failed to turn off swaps: %s", strerror(-r)); + log_error("Failed to deactivate swaps: %s", strerror(-r)); } if (need_loop_detach) { log_info("Detaching loop devices."); r = loopback_detach_all(&changed); - if (r == 0) + if (r == 0) { need_loop_detach = false; - else if (r > 0) + log_info("All loop devices detached."); + } else if (r > 0) log_info("Not all loop devices detached, %d left.", r); else log_error("Failed to detach loop devices: %s", strerror(-r)); @@ -230,10 +233,11 @@ int main(int argc, char *argv[]) { if (need_dm_detach) { log_info("Detaching DM devices."); r = dm_detach_all(&changed); - if (r == 0) + if (r == 0) { need_dm_detach = false; - else if (r > 0) - log_warning("Not all DM devices detached, %d left.", r); + log_info("All DM devices detached."); + } else if (r > 0) + log_info("Not all DM devices detached, %d left.", r); else log_error("Failed to detach DM devices: %s", strerror(-r)); } @@ -263,14 +267,8 @@ int main(int argc, char *argv[]) { arguments[2] = NULL; execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments); - /* If we are in a container, just exit, this will kill our - * container for good. */ - if (in_container) { - log_error("Exiting container."); - exit(0); - } - - if (access("/run/initramfs/shutdown", X_OK) == 0) { + if (!in_container && !in_initrd() && + access("/run/initramfs/shutdown", X_OK) == 0) { if (prepare_new_root() >= 0 && pivot_to_new_root() >= 0) { @@ -279,26 +277,45 @@ int main(int argc, char *argv[]) { } } + /* The kernel will automaticall flush ATA disks and suchlike + * on reboot(), but the file systems need to be synce'd + * explicitly in advance. So let's do this here, but not + * needlessly slow down containers. */ + if (!in_container) + sync(); + if (cmd == LINUX_REBOOT_CMD_KEXEC) { - /* We cheat and exec kexec to avoid doing all its work */ - pid_t pid = fork(); - - if (pid < 0) - log_error("Could not fork: %m. Falling back to normal reboot."); - else if (pid > 0) { - wait_for_terminate_and_warn("kexec", pid); - log_warning("kexec failed. Falling back to normal reboot."); - } else { - /* Child */ - const char *args[3] = { "/sbin/kexec", "-e", NULL }; - execv(args[0], (char * const *) args); - return EXIT_FAILURE; + + if (!in_container) { + /* We cheat and exec kexec to avoid doing all its work */ + pid_t pid = fork(); + + if (pid < 0) + log_error("Could not fork: %m. Falling back to normal reboot."); + else if (pid > 0) { + wait_for_terminate_and_warn("kexec", pid); + log_warning("kexec failed. Falling back to normal reboot."); + } else { + /* Child */ + const char *args[3] = { "/sbin/kexec", "-e", NULL }; + execv(args[0], (char * const *) args); + return EXIT_FAILURE; + } } cmd = RB_AUTOBOOT; } reboot(cmd); + + if (errno == EPERM && in_container) { + /* If we are in a container, and we lacked + * CAP_SYS_BOOT just exit, this will kill our + * container for good. */ + log_error("Exiting container."); + exit(0); + } + log_error("Failed to invoke reboot(): %m"); r = -errno;