X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fshutdown.c;h=377c1971a37d130bc9addaf6f639e82a11d37c3d;hb=3f41e1e5955552a771748225334b3e8a7eb02b8a;hp=0b0e0c3d476c3d10c74ce0044706adf1c291195e;hpb=f274ece0f76b5709408821e317e87aef76123db6;p=elogind.git diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 0b0e0c3d4..377c1971a 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -39,12 +39,15 @@ #include "missing.h" #include "log.h" +#include "fileio.h" #include "umount.h" #include "util.h" #include "mkdir.h" #include "virt.h" #include "watchdog.h" #include "killall.h" +#include "cgroup-util.h" +#include "def.h" #define FINALIZE_ATTEMPTS 50 @@ -130,11 +133,26 @@ static int pivot_to_new_root(void) { } int main(int argc, char *argv[]) { - int cmd, r; - unsigned retries; bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true; bool in_container, use_watchdog = false; + _cleanup_free_ char *line = NULL, *cgroup = NULL, *param = NULL; char *arguments[3]; + unsigned retries; + int cmd, r; + + /* suppress shutdown status output if 'quiet' is used */ + r = proc_cmdline(&line); + if (r > 0) { + char *w, *state; + size_t l; + + FOREACH_WORD_QUOTED(w, l, line, state) { + if (l == 5 && memcmp(w, "quiet", 5) == 0) { + log_set_max_level(LOG_WARNING); + break; + } + } + } log_parse_environment(); log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */ @@ -156,9 +174,11 @@ int main(int argc, char *argv[]) { in_container = detect_container(NULL) > 0; - if (streq(argv[1], "reboot")) + if (streq(argv[1], "reboot")) { cmd = RB_AUTOBOOT; - else if (streq(argv[1], "poweroff")) + /* if this fails, that's OK */ + read_one_line_file(REBOOT_PARAM_FILE, ¶m); + } else if (streq(argv[1], "poweroff")) cmd = RB_POWER_OFF; else if (streq(argv[1], "halt")) cmd = RB_HALT_SYSTEM; @@ -170,6 +190,8 @@ int main(int argc, char *argv[]) { goto error; } + cg_get_root_path(&cgroup); + use_watchdog = !!getenv("WATCHDOG_USEC"); /* lock us into memory */ @@ -194,6 +216,13 @@ int main(int argc, char *argv[]) { if (use_watchdog) watchdog_ping(); + /* Let's trim the cgroup tree on each iteration so + that we leave an empty cgroup tree around, so that + container managers get a nice notify event when we + are down */ + if (cgroup) + cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false); + if (need_umount) { log_info("Unmounting file systems."); r = umount_all(&changed); @@ -261,6 +290,8 @@ int main(int argc, char *argv[]) { if (retries >= FINALIZE_ATTEMPTS) log_error("Too many iterations, giving up."); + else + log_info("Storage is finalized."); arguments[0] = NULL; arguments[1] = argv[1]; @@ -272,6 +303,9 @@ int main(int argc, char *argv[]) { if (prepare_new_root() >= 0 && pivot_to_new_root() >= 0) { + + log_info("Returning to initrd..."); + execv("/shutdown", argv); log_error("Failed to execute shutdown binary: %m"); } @@ -297,7 +331,7 @@ int main(int argc, char *argv[]) { log_warning("kexec failed. Falling back to normal reboot."); } else { /* Child */ - const char *args[3] = { "/sbin/kexec", "-e", NULL }; + const char *args[3] = { KEXEC, "-e", NULL }; execv(args[0], (char * const *) args); return EXIT_FAILURE; } @@ -306,7 +340,11 @@ int main(int argc, char *argv[]) { cmd = RB_AUTOBOOT; } - reboot(cmd); + if (param) + syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, param); + else + reboot(cmd); if (errno == EPERM && in_container) { /* If we are in a container, and we lacked