diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md
index 65d28e6bfa..b6e5c2e156 100644
--- a/docs/ENVIRONMENT.md
+++ b/docs/ENVIRONMENT.md
@@ -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
diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml
index 4a94656f66..954518992b 100644
--- a/man/org.freedesktop.login1.xml
+++ b/man/org.freedesktop.login1.xml
@@ -595,16 +595,20 @@ node /org/freedesktop/login1 {
SuspendThenHibernateWithFlags() add flags to allow for
extendability, defined as follows:
-#define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0)
-#define SD_LOGIND_KEXEC_REBOOT (UINT64_C(1) << 1)
-#define SD_LOGIND_SOFT_REBOOT (UINT64_C(1) << 2)
+#define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0)
+#define SD_LOGIND_KEXEC_REBOOT (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)
When the flags is 0 then these methods behave just like the versions without
flags. When SD_LOGIND_ROOT_CHECK_INHIBITORS (0x01) is set, active inhibitors are
- honoured for privileged users too. When SD_LOGIND_KEXEC_REBOOT (0x02) is set, then
- RebootWithFlags() performs a kexec reboot if kexec kernel is loaded. When
- SD_LOGIND_SOFT_REBOOT (0x04) is set, then RebootWithFlags()
- performs a userspace reboot only.
+ honoured for privileged users too. When SD_LOGIND_KEXEC_REBOOT (0x02) is set,
+ then RebootWithFlags() performs a kexec reboot if kexec kernel is loaded. When
+ SD_LOGIND_SOFT_REBOOT (0x04) is set, or
+ SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP (0x08) is set and a new root file system
+ has been set up on /run/nextroot/, then RebootWithFlags()
+ performs a userspace reboot only. SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP and
+ SD_LOGIND_KEXEC_REBOOT can be combined, with soft-reboot having precedence.
SetRebootParameter() sets a parameter for a subsequent reboot operation.
See the description of reboot in
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 419d4a8243..217010ca1c 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1652,6 +1652,13 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
This command honors and in a similar way
as halt.
+ If a new kernel has been loaded via kexec --load, a
+ kexec will be performed instead of a reboot, unless
+ SYSTEMCTL_SKIP_AUTO_KEXEC=1 has been set. If a new root file system has
+ been setup on /run/nextroot, a soft-reboot will be
+ performed instead of a reboot, unless SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT=1 has
+ been set.
+
@@ -1681,6 +1688,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
This command honors and similarly
to halt.
+
+ If a new kernel has been loaded via kexec --load, a
+ kexec will be performed when reboot is invoked, unless
+ SYSTEMCTL_SKIP_AUTO_KEXEC=1 has been set.
@@ -1700,6 +1711,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
systemd-soft-reboot.service8
for details.
+ If a new root file system has been setup on /run/nextroot, a
+ soft-reboot will be performed when reboot is invoked,
+ unless SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT=1 has been set.
+
diff --git a/man/systemd-soft-reboot.service.xml b/man/systemd-soft-reboot.service.xml
index 1de2fbc5f3..2419b86604 100644
--- a/man/systemd-soft-reboot.service.xml
+++ b/man/systemd-soft-reboot.service.xml
@@ -164,6 +164,10 @@ ExecStart=sleep infinity
Note that systemd-soft-reboot.service (and related units) should never be
executed directly. Instead, trigger system shutdown with a command such as systemctl
soft-reboot.
+
+ Note that if a new root file system has been setup on /run/nextroot, a
+ soft-reboot will be performed when the reboot command is
+ invoked.
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
index 613fb0f86f..4c9cae0f4f 100644
--- a/src/basic/login-util.h
+++ b/src/basic/login-util.h
@@ -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);
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index b458359c97..d631a30716 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -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)
diff --git a/src/systemctl/systemctl-logind.c b/src/systemctl/systemctl-logind.c
index 2a697b84e5..cd83d29474 100644
--- a/src/systemctl/systemctl-logind.c
+++ b/src/systemctl/systemctl-logind.c
@@ -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);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index dcd4dcc68a..70b8c16249 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -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")) {
diff --git a/test/units/testsuite-82.sh b/test/units/testsuite-82.sh
index 15243ab6a2..e0f9573f54 100755
--- a/test/units/testsuite-82.sh
+++ b/test/units/testsuite-82.sh
@@ -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