]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
logind: Add new flag for kexec reboot
authorDeepak Rawat <drawat.floss@gmail.com>
Tue, 30 Mar 2021 03:22:16 +0000 (20:22 -0700)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 31 Mar 2021 08:48:48 +0000 (10:48 +0200)
Add new flag to allow kexec reboot if kernel is already loaded.

man/org.freedesktop.login1.xml
src/basic/login-util.h
src/login/logind-dbus.c
src/systemctl/systemctl-compat-halt.c
src/systemctl/systemctl-logind.c
src/systemctl/systemctl-start-special.c

index bf7a5fa3402d843958cb35c82b2a2835106b85bd..70410fc72672e562db184f3c85aef09cb70c4042 100644 (file)
@@ -555,10 +555,13 @@ node /org/freedesktop/login1 {
       extendability, defined as follows:</para>
       <programlisting>
 #define SD_LOGIND_ROOT_CHECK_INHIBITORS  (UINT64_C(1) &lt;&lt; 0)
+#define SD_LOGIND_KEXEC_REBOOT           (UINT64_C(1) &lt;&lt; 1)
       </programlisting>
       <para> When the <varname>flags</varname> is 0 then these methods behave just like the versions
       without flags. When <constant>SD_LOGIND_ROOT_CHECK_INHIBITORS</constant> (0x01) is set, active
-      inhibitors are honoured for privileged users too.</para>
+      inhibitors are honoured for privileged users too. When <constant>SD_LOGIND_KEXEC_REBOOT</constant>
+      (0x02) is set, then <function>RebootWithFlags()</function> perform kexec reboot if kexec
+      kernel is loaded.</para>
 
       <para><function>SetRebootParameter()</function> sets a parameter for a subsequent reboot operation.
       See the description of <command>reboot</command> in
index dff87697a64c0dd830a67f08d3eaacdd10c755a3..dc63fffdea37583db72daaeccdc08f4e9ec46d8b 100644 (file)
@@ -5,12 +5,13 @@
 #include <unistd.h>
 
 #define SD_LOGIND_ROOT_CHECK_INHIBITORS           (UINT64_C(1) << 0)
+#define SD_LOGIND_KEXEC_REBOOT                    (UINT64_C(1) << 1)
 
 /* For internal use only */
 #define SD_LOGIND_INTERACTIVE                     (UINT64_C(1) << 63)
 
-#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS)
-#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL    (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_INTERACTIVE)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_KEXEC_REBOOT)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL    (SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC|SD_LOGIND_INTERACTIVE)
 
 bool session_id_valid(const char *id);
 
index a539a2e9797d2e2a78336d32dbc52fa489a09434..532be12e7a3cf2dbd83c7e3bd45e5cdc1c00df8e 100644 (file)
@@ -1880,6 +1880,8 @@ static int method_do_shutdown_or_sleep(
                         return r;
                 if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
+                if (!streq(unit_name, SPECIAL_REBOOT_TARGET) && (flags & SD_LOGIND_KEXEC_REBOOT))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
         } else {
                 /* Old style method: no flags parameter, but interactive bool passed as boolean in
                  * payload. Let's convert this argument to the new-style flags parameter for our internal
@@ -1893,6 +1895,9 @@ static int method_do_shutdown_or_sleep(
                 flags = interactive ? SD_LOGIND_INTERACTIVE : 0;
         }
 
+        if ((flags & SD_LOGIND_KEXEC_REBOOT) && kexec_loaded())
+                unit_name = SPECIAL_KEXEC_TARGET;
+
         /* Don't allow multiple jobs being executed at the same time */
         if (m->action_what > 0)
                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
index 82cb3df6cdd332acdc6ce8a85d2a78798c63d4d2..51a89ae4a737db7e8c6d9333408dc422a8c87b66 100644 (file)
@@ -161,7 +161,7 @@ int halt_main(void) {
 
                 /* Try logind if we are a normal user and no special mode applies. Maybe polkit allows us to
                  * shutdown the machine. */
-                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) {
+                if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_KEXEC, ACTION_HALT)) {
                         r = logind_reboot(arg_action);
                         if (r >= 0)
                                 return r;
index 103f81647d26e5f5d52bd19d2cbb0a8e7220c276..15e396ebd7a38301a4812776b992ac6fd0d1f738 100644 (file)
@@ -50,6 +50,7 @@ int logind_reboot(enum action a) {
         } actions[_ACTION_MAX] = {
                 [ACTION_POWEROFF]               = { "PowerOff",             "power off system"                },
                 [ACTION_REBOOT]                 = { "Reboot",               "reboot system"                   },
+                [ACTION_KEXEC]                  = { "Reboot",               "kexec reboot system"             },
                 [ACTION_HALT]                   = { "Halt",                 "halt system"                     },
                 [ACTION_SUSPEND]                = { "Suspend",              "suspend system"                  },
                 [ACTION_HIBERNATE]              = { "Hibernate",            "hibernate system"                },
@@ -79,6 +80,7 @@ int logind_reboot(enum action a) {
                 return 0;
 
         SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
+        SET_FLAG(flags, SD_LOGIND_KEXEC_REBOOT, a == ACTION_KEXEC);
 
         method_with_flags = strjoina(actions[a].method, "WithFlags");
 
index 15d2ea7941f84b3a57447a761c999da847a2c2d0..3edb65be617181b3b879ced38ad0fd69d99fb141 100644 (file)
@@ -201,6 +201,7 @@ int start_special(int argc, char *argv[], void *userdata) {
                 if (IN_SET(a,
                            ACTION_POWEROFF,
                            ACTION_REBOOT,
+                           ACTION_KEXEC,
                            ACTION_HALT,
                            ACTION_SUSPEND,
                            ACTION_HIBERNATE,
@@ -220,9 +221,9 @@ int start_special(int argc, char *argv[], void *userdata) {
 
                         arg_no_block = true;
 
-                } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC))
-                        /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make
-                         * them asynchronous, in order to not confuse the user needlessly with unexpected
+                } else if (IN_SET(a, ACTION_EXIT))
+                        /* Since exit is so close in behaviour to power-off/reboot, let's also make
+                         * it asynchronous, in order to not confuse the user needlessly with unexpected
                          * behaviour. */
                         arg_no_block = true;