chiark / gitweb /
shutdown: unify handling of reboot() syscall a bit
authorLennart Poettering <lennart@poettering.net>
Fri, 8 Nov 2013 18:32:45 +0000 (19:32 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 8 Nov 2013 18:32:45 +0000 (19:32 +0100)
TODO
src/core/shutdown.c
src/shared/util.c
src/systemctl/systemctl.c

diff --git a/TODO b/TODO
index e08e11e..9f83a24 100644 (file)
--- a/TODO
+++ b/TODO
@@ -46,9 +46,11 @@ CGroup Rework Completion:
 
 Features:
 
+* increase journal files by a few MB each time, instead of piecemeal
+
 * add field to transient units that indicate whether systemd or somebody else saves/restores its settings, for integration with libvirt
 
-* wait filter, reboot() filter unification, unify dispatch table in systemctl_main() and friends, convert all to bus_log_create_error()
+* wait filter, unify dispatch table in systemctl_main() and friends, convert all to bus_log_create_error()
 
 * bus: access policy as vtable flag
 
index 377c197..b5eb8b1 100644 (file)
@@ -135,7 +135,7 @@ static int pivot_to_new_root(void) {
 int main(int argc, char *argv[]) {
         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;
+        _cleanup_free_ char *line = NULL, *cgroup = NULL;
         char *arguments[3];
         unsigned retries;
         int cmd, r;
@@ -174,11 +174,9 @@ 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;
-                /* if this fails, that's OK */
-                read_one_line_file(REBOOT_PARAM_FILE, &param);
-        } else if (streq(argv[1], "poweroff"))
+        else if (streq(argv[1], "poweroff"))
                 cmd = RB_POWER_OFF;
         else if (streq(argv[1], "halt"))
                 cmd = RB_HALT_SYSTEM;
@@ -318,39 +316,69 @@ int main(int argc, char *argv[]) {
         if (!in_container)
                 sync();
 
-        if (cmd == LINUX_REBOOT_CMD_KEXEC) {
+        switch (cmd) {
+
+        case LINUX_REBOOT_CMD_KEXEC:
 
                 if (!in_container) {
                         /* We cheat and exec kexec to avoid doing all its work */
-                        pid_t pid = fork();
+                        pid_t pid;
+
+                        log_info("Rebooting with kexec.");
 
+                        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 {
+                                log_error("Failed to fork: %m");
+                        else if (pid == 0) {
+
+                                const char * const args[] = {
+                                        KEXEC, "-e", NULL
+                                };
+
                                 /* Child */
-                                const char *args[3] = { KEXEC, "-e", NULL };
+
                                 execv(args[0], (char * const *) args);
-                                return EXIT_FAILURE;
-                        }
+                                _exit(EXIT_FAILURE);
+                        } else
+                                wait_for_terminate_and_warn("kexec", pid);
                 }
 
                 cmd = RB_AUTOBOOT;
-        }
+                /* Fall through */
 
-        if (param)
-                syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
-                        LINUX_REBOOT_CMD_RESTART2, param);
-        else
-                reboot(cmd);
+        case RB_AUTOBOOT:
+
+                if (!in_container) {
+                        _cleanup_free_ char *param = NULL;
+
+                        if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
+                                log_info("Rebooting with argument '%s'.", param);
+                                syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                                        LINUX_REBOOT_CMD_RESTART2, param);
+                        }
+                }
+
+                log_info("Rebooting.");
+                break;
+
+        case RB_POWER_OFF:
+                log_info("Powering off.");
+                break;
+
+        case RB_HALT_SYSTEM:
+                log_info("Halting system.");
+                break;
+
+        default:
+                assert_not_reached("Unknown magic");
+        }
 
+        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.");
+                log_info("Exiting container.");
                 exit(0);
         }
 
index a6669c5..838885a 100644 (file)
@@ -77,6 +77,7 @@
 #include "utf8.h"
 #include "gunicode.h"
 #include "virt.h"
+#include "def.h"
 
 int saved_argc = 0;
 char **saved_argv = NULL;
index 6380086..c042da5 100644 (file)
@@ -135,7 +135,7 @@ static OutputMode arg_output = OUTPUT_SHORT;
 static bool arg_plain = false;
 
 static int daemon_reload(sd_bus *bus, char **args);
-static void halt_now(enum action a);
+static int halt_now(enum action a);
 
 static void pager_open_if_enabled(void) {
 
@@ -2033,7 +2033,7 @@ static int start_special(sd_bus *bus, char **args) {
             (a == ACTION_HALT ||
              a == ACTION_POWEROFF ||
              a == ACTION_REBOOT))
-                halt_now(a);
+                return halt_now(a);
 
         if (arg_force >= 1 &&
             (a == ACTION_HALT ||
@@ -5609,11 +5609,9 @@ done:
         return 0;
 }
 
-static _noreturn_ void halt_now(enum action a) {
+static int halt_now(enum action a) {
 
-        _cleanup_free_ char *param = NULL;
-
-       /* Make sure C-A-D is handled by the kernel from this
+/* Make sure C-A-D is handled by the kernel from this
          * point on... */
         reboot(RB_ENABLE_CAD);
 
@@ -5622,30 +5620,30 @@ static _noreturn_ void halt_now(enum action a) {
         case ACTION_HALT:
                 log_info("Halting.");
                 reboot(RB_HALT_SYSTEM);
-                break;
+                return -errno;
 
         case ACTION_POWEROFF:
                 log_info("Powering off.");
                 reboot(RB_POWER_OFF);
-                break;
+                return -errno;
 
-        case ACTION_REBOOT:
+        case ACTION_REBOOT: {
+                _cleanup_free_ char *param = NULL;
 
-                if (read_one_line_file(REBOOT_PARAM_FILE, &param) == 0) {
-                        log_info("Rebooting with arg '%s'.", param);
+                if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
+                        log_info("Rebooting with argument '%s'.", param);
                         syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                                 LINUX_REBOOT_CMD_RESTART2, param);
-                } else {
-                        log_info("Rebooting.");
-                        reboot(RB_AUTOBOOT);
                 }
-                break;
 
-        default:
-                assert_not_reached("Unknown halt action.");
+                log_info("Rebooting.");
+                reboot(RB_AUTOBOOT);
+                return -errno;
         }
 
-        assert_not_reached("Uh? This shouldn't happen.");
+        default:
+                assert_not_reached("Unknown action.");
+        }
 }
 
 static int halt_main(sd_bus *bus) {
@@ -5717,9 +5715,10 @@ static int halt_main(sd_bus *bus) {
         if (arg_dry)
                 return 0;
 
-        halt_now(arg_action);
-        /* We should never reach this. */
-        return -ENOSYS;
+        r = halt_now(arg_action);
+        log_error("Failed to reboot: %s", strerror(-r));
+
+        return r;
 }
 
 static int runlevel_main(void) {