]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: automatically softreboot/kexec if set up on reboot 29626/head
authorLuca Boccassi <bluca@debian.org>
Thu, 19 Oct 2023 12:58:03 +0000 (13:58 +0100)
committerLuca Boccassi <bluca@debian.org>
Fri, 20 Oct 2023 10:45:37 +0000 (11:45 +0100)
Automatically softreboot if the nextroot has been set up with an OS
tree, or automatically kexec if a kernel has been loaded with kexec
--load.

Add SYSTEMCTL_SKIP_AUTO_KEXEC and SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT to
skip the automated switchover.

docs/ENVIRONMENT.md
man/org.freedesktop.login1.xml
man/systemctl.xml
man/systemd-soft-reboot.service.xml
src/basic/login-util.h
src/login/logind-dbus.c
src/systemctl/systemctl-logind.c
src/systemctl/systemctl.c
test/units/testsuite-82.sh

index 65d28e6bfa6edef5093da76bc254c0fc4375579e..b6e5c2e1567586df34cf7f93488889a472c7d50f 100644 (file)
@@ -136,6 +136,13 @@ All tools:
 
 * `$SYSTEMCTL_SKIP_SYSV=1` — if set, do not call SysV compatibility hooks.
 
+* `$SYSTEMCTL_SKIP_AUTO_KEXEC=1` — if set, do not automatically kexec instead of
+  reboot when a new kernel has been loaded.
+
+* `$SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT=1` — if set, do not automatically soft-reboot
+  instead of reboot when a new root file system has been loaded in
+  `/run/nextroot`.
+
 `systemd-nspawn`:
 
 * `$SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=1` — if set, force `systemd-nspawn` into
index 4a94656f6625d921c3090b253755684fb4cce60c..954518992be5dd5880da631694b2f661fea64a2a 100644 (file)
@@ -595,16 +595,20 @@ node /org/freedesktop/login1 {
       <function>SuspendThenHibernateWithFlags()</function> add <varname>flags</varname> to allow for
       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)
-#define SD_LOGIND_SOFT_REBOOT            (UINT64_C(1) &lt;&lt; 2)
+#define SD_LOGIND_ROOT_CHECK_INHIBITORS          (UINT64_C(1) &lt;&lt; 0)
+#define SD_LOGIND_KEXEC_REBOOT                   (UINT64_C(1) &lt;&lt; 1)
+#define SD_LOGIND_SOFT_REBOOT                    (UINT64_C(1) &lt;&lt; 2)
+#define SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP (UINT64_C(1) &lt;&lt; 3)
       </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. When <constant>SD_LOGIND_KEXEC_REBOOT</constant> (0x02) is set, then
-      <function>RebootWithFlags()</function> performs a kexec reboot if kexec kernel is loaded. When
-      <constant>SD_LOGIND_SOFT_REBOOT</constant> (0x04) is set, then <function>RebootWithFlags()</function>
-      performs a userspace reboot only.</para>
+      honoured for privileged users too. When <constant>SD_LOGIND_KEXEC_REBOOT</constant> (0x02) is set,
+      then <function>RebootWithFlags()</function> performs a kexec reboot if kexec kernel is loaded. When
+      <constant>SD_LOGIND_SOFT_REBOOT</constant> (0x04) is set, or
+      <constant>SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP</constant> (0x08) is set and a new root file system
+      has been set up on <literal>/run/nextroot/</literal>, then <function>RebootWithFlags()</function>
+      performs a userspace reboot only. <constant>SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP</constant> and
+      <constant>SD_LOGIND_KEXEC_REBOOT</constant> can be combined, with soft-reboot having precedence.</para>
 
       <para><function>SetRebootParameter()</function> sets a parameter for a subsequent reboot operation.
       See the description of <command>reboot</command> in
index 419d4a82438f80dc465e0c3c9cb3c624e444c6e5..217010ca1c80a30f50361ec7f6c1ffa26bdde4d3 100644 (file)
@@ -1652,6 +1652,13 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
             <para>This command honors <option>--force</option> and <option>--when=</option> in a similar way
             as <command>halt</command>.</para>
 
+            <para>If a new kernel has been loaded via <command>kexec --load</command>, a
+            <command>kexec</command> will be performed instead of a reboot, unless
+            <literal>SYSTEMCTL_SKIP_AUTO_KEXEC=1</literal> has been set. If a new root file system has
+            been setup on <literal>/run/nextroot</literal>, a <command>soft-reboot</command> will be
+            performed instead of a reboot, unless <literal>SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT=1</literal> has
+            been set.</para>
+
             <xi:include href="version-info.xml" xpointer="v246"/>
           </listitem>
         </varlistentry>
@@ -1681,6 +1688,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
 
             <para>This command honors <option>--force</option> and <option>--when=</option> similarly
             to <command>halt</command>.</para>
+
+            <para>If a new kernel has been loaded via <command>kexec --load</command>, a
+            <command>kexec</command> will be performed when <command>reboot</command> is invoked, unless
+            <literal>SYSTEMCTL_SKIP_AUTO_KEXEC=1</literal> has been set.</para>
           </listitem>
         </varlistentry>
 
@@ -1700,6 +1711,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
             <citerefentry><refentrytitle>systemd-soft-reboot.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
             for details.</para>
 
+            <para>If a new root file system has been setup on <literal>/run/nextroot</literal>, a
+            <command>soft-reboot</command> will be performed when <command>reboot</command> is invoked,
+            unless <literal>SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT=1</literal> has been set.</para>
+
             <xi:include href="version-info.xml" xpointer="v254"/>
           </listitem>
         </varlistentry>
index 1de2fbc5f376c0ff001975076c4f7e8c3cc4c05e..2419b8660494fcc62405d23b27f73d944417d2a7 100644 (file)
@@ -164,6 +164,10 @@ ExecStart=sleep infinity
     <para>Note that <filename>systemd-soft-reboot.service</filename> (and related units) should never be
     executed directly. Instead, trigger system shutdown with a command such as <literal>systemctl
     soft-reboot</literal>.</para>
+
+    <para>Note that if a new root file system has been setup on <literal>/run/nextroot</literal>, a
+    <command>soft-reboot</command> will be performed when the <command>reboot</command> command is
+    invoked.</para>
   </refsect1>
 
   <refsect1>
index 613fb0f86f48d99cb33e4c19fc5050f9c081c83f..4c9cae0f4fc57e2048c881d6ecad3a28d9b371c6 100644 (file)
@@ -7,11 +7,12 @@
 #define SD_LOGIND_ROOT_CHECK_INHIBITORS           (UINT64_C(1) << 0)
 #define SD_LOGIND_REBOOT_VIA_KEXEC                (UINT64_C(1) << 1)
 #define SD_LOGIND_SOFT_REBOOT                     (UINT64_C(1) << 2)
+#define SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP  (UINT64_C(1) << 3)
 
 /* 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|SD_LOGIND_REBOOT_VIA_KEXEC|SD_LOGIND_SOFT_REBOOT)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_REBOOT_VIA_KEXEC|SD_LOGIND_SOFT_REBOOT|SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP)
 #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 b458359c971b8605ba51b3533698cd71a181076b..d631a3071668bc5297d4a967b9f671d34e9d1153 100644 (file)
@@ -1895,7 +1895,7 @@ static int method_do_shutdown_or_sleep(
                         if (flags & SD_LOGIND_REBOOT_VIA_KEXEC)
                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
                                                         "Reboot via kexec option is only applicable with reboot operations");
-                        if (flags & SD_LOGIND_SOFT_REBOOT)
+                        if ((flags & SD_LOGIND_SOFT_REBOOT) || (flags & SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP))
                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
                                                         "Soft reboot option is only applicable with reboot operations");
                 }
@@ -1912,10 +1912,11 @@ static int method_do_shutdown_or_sleep(
                 flags = interactive ? SD_LOGIND_INTERACTIVE : 0;
         }
 
-        if ((flags & SD_LOGIND_REBOOT_VIA_KEXEC) && kexec_loaded())
-                a = handle_action_lookup(HANDLE_KEXEC);
-        else if ((flags & SD_LOGIND_SOFT_REBOOT))
+        if ((flags & SD_LOGIND_SOFT_REBOOT) ||
+            ((flags & SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP) && path_is_os_tree("/run/nextroot") > 0))
                 a = handle_action_lookup(HANDLE_SOFT_REBOOT);
+        else if ((flags & SD_LOGIND_REBOOT_VIA_KEXEC) && kexec_loaded())
+                a = handle_action_lookup(HANDLE_KEXEC);
 
         /* Don't allow multiple jobs being executed at the same time */
         if (m->delayed_action)
index 2a697b84e53f976166efd30e6b5d90fb5b77ba6b..cd83d29474a4ebeeb63ff90af30d1e17eff980e6 100644 (file)
@@ -80,7 +80,12 @@ 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_REBOOT_VIA_KEXEC, a == ACTION_KEXEC);
+        SET_FLAG(flags,
+                 SD_LOGIND_REBOOT_VIA_KEXEC,
+                 a == ACTION_KEXEC || (a == ACTION_REBOOT && getenv_bool("SYSTEMCTL_SKIP_AUTO_KEXEC") <= 0));
+        SET_FLAG(flags,
+                 SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP,
+                 a == ACTION_REBOOT && getenv_bool("SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT") <= 0);
         SET_FLAG(flags, SD_LOGIND_SOFT_REBOOT, a == ACTION_SOFT_REBOOT);
 
         r = bus_call_method(bus, bus_login_mgr, method_with_flags, &error, NULL, "t", flags);
index dcd4dcc68aae29eb90cdf190d411b9843990e707..70b8c16249413ebcdf512b5a0271f74d8f77b9a8 100644 (file)
@@ -1090,10 +1090,7 @@ int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
                 return halt_parse_argv(argc, argv);
 
         } else if (invoked_as(argv, "reboot")) {
-                if (kexec_loaded())
-                        arg_action = ACTION_KEXEC;
-                else
-                        arg_action = ACTION_REBOOT;
+                arg_action = ACTION_REBOOT;
                 return halt_parse_argv(argc, argv);
 
         } else if (invoked_as(argv, "shutdown")) {
index 15243ab6a222dee5d3fbff6ba1365ccd06f31ced..e0f9573f54106890cb97876cd0b6ed622d9a7995 100755 (executable)
@@ -133,9 +133,10 @@ elif [ -f /run/testsuite82.touch ]; then
     # Restart the unit that is not supposed to survive
     systemd-run --collect --service-type=exec --unit=testsuite-82-nosurvive.service sleep infinity
 
-    # Now issue the soft reboot. We should be right back soon.
+    # Now issue the soft reboot. We should be right back soon. Given /run/nextroot exists, we should
+    # automatically do a softreboot instead of normal reboot.
     touch /run/testsuite82.touch2
-    systemctl --no-block soft-reboot
+    systemctl --no-block reboot
 
     # Now block until the soft-boot killing spree kills us
     exec sleep infinity