X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fshutdown.c;h=aa9548e2a4700bb567aab34bb56db862902e659e;hb=eb9da376d76b48585b3b63b4f91903b54f7abd36;hp=192746a9532b07525719cc7b68610a4cd1f96f16;hpb=2569a5ce16638d99f1ebaaa7774d183496d8b8e8;p=elogind.git diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 192746a95..aa9548e2a 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -39,12 +39,14 @@ #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" #define FINALIZE_ATTEMPTS 50 @@ -130,11 +132,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; 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 */ @@ -170,6 +187,8 @@ int main(int argc, char *argv[]) { goto error; } + cg_get_root_path(&cgroup); + use_watchdog = !!getenv("WATCHDOG_USEC"); /* lock us into memory */ @@ -194,34 +213,44 @@ 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); - 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,9 +259,10 @@ 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_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)); @@ -257,6 +287,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]; @@ -268,6 +300,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"); } @@ -293,7 +328,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; }