From: Luca Boccassi Date: Fri, 27 Mar 2026 19:32:29 +0000 (+0000) Subject: shutdown: remove kexec-tools dependency X-Git-Tag: v261-rc1~700 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1224e5d1952598db6706bf2e70f9cbfde6fe0987;p=thirdparty%2Fsystemd.git shutdown: remove kexec-tools dependency 'kexec -e' is just a small wrapper that does the xen hypercall on xen, or otherwise just calls reboot(). Drop the dependency, and reuse the existing xen hypercall helper. --- diff --git a/src/login/logind-action.c b/src/login/logind-action.c index 843bb1a5a08..48f2031fc47 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -222,10 +222,6 @@ static int handle_action_execute( assert(m); assert(!IN_SET(handle, HANDLE_IGNORE, HANDLE_LOCK, HANDLE_SLEEP)); - if (handle == HANDLE_KEXEC && access(KEXEC, X_OK) < 0) - return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Requested %s operation not supported, ignoring.", handle_action_to_string(handle)); - if (m->delayed_action) return log_debug_errno(SYNTHETIC_ERRNO(EALREADY), "Action %s already in progress, ignoring requested %s operation.", diff --git a/src/shared/reboot-util.c b/src/shared/reboot-util.c index 55ec6c0f0aa..d9ff532921b 100644 --- a/src/shared/reboot-util.c +++ b/src/shared/reboot-util.c @@ -139,13 +139,15 @@ bool shall_restore_state(void) { return (cached = b); } -static int xen_kexec_loaded(void) { #if HAVE_XENCTRL +static int xen_kexec_command(uint64_t cmd) { _cleanup_close_ int privcmd_fd = -EBADF, buf_fd = -EBADF; - xen_kexec_status_t *buffer; + void *buffer; size_t size; int r; + assert(IN_SET(cmd, KEXEC_CMD_kexec, KEXEC_CMD_kexec_status)); + if (access("/proc/xen", F_OK) < 0) { if (errno == ENOENT) return -EOPNOTSUPP; @@ -153,7 +155,8 @@ static int xen_kexec_loaded(void) { } size = page_size(); - if (sizeof(xen_kexec_status_t) > size) + if ((cmd == KEXEC_CMD_kexec_status && sizeof(xen_kexec_status_t) > size) || + (cmd == KEXEC_CMD_kexec && sizeof(xen_kexec_exec_t) > size)) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "page_size is too small for hypercall"); privcmd_fd = open("/dev/xen/privcmd", O_RDWR|O_CLOEXEC); @@ -168,25 +171,44 @@ static int xen_kexec_loaded(void) { if (buffer == MAP_FAILED) return log_debug_errno(errno, "Cannot allocate buffer for hypercall: %m"); - *buffer = (xen_kexec_status_t) { - .type = KEXEC_TYPE_DEFAULT, - }; + if (cmd == KEXEC_CMD_kexec_status) + *(xen_kexec_status_t *)buffer = (xen_kexec_status_t) { + .type = KEXEC_TYPE_DEFAULT, + }; + else + *(xen_kexec_exec_t *)buffer = (xen_kexec_exec_t) { + .type = KEXEC_TYPE_DEFAULT, + }; privcmd_hypercall_t call = { .op = __HYPERVISOR_kexec_op, .arg = { - KEXEC_CMD_kexec_status, + cmd, PTR_TO_UINT64(buffer), }, }; r = RET_NERRNO(ioctl(privcmd_fd, IOCTL_PRIVCMD_HYPERCALL, &call)); if (r < 0) - log_debug_errno(r, "kexec_status failed: %m"); + log_debug_errno(r, "kexec%s failed: %m", cmd == KEXEC_CMD_kexec_status ? "_status" : ""); munmap(buffer, size); return r; +} +#endif + +static int xen_kexec(void) { +#if HAVE_XENCTRL + return xen_kexec_command(KEXEC_CMD_kexec); +#else + return -EOPNOTSUPP; +#endif +} + +static int xen_kexec_loaded(void) { +#if HAVE_XENCTRL + return xen_kexec_command(KEXEC_CMD_kexec_status); #else return -EOPNOTSUPP; #endif @@ -210,6 +232,20 @@ bool kexec_loaded(void) { return s[0] == '1'; } +int kexec(void) { + int r; + + r = xen_kexec(); + if (r < 0 && r != -EOPNOTSUPP) + return log_error_errno(r, "Failed to call xen kexec: %m"); + + r = reboot(LINUX_REBOOT_CMD_KEXEC); + if (r < 0) + return log_error_errno(errno, "Failed to kexec: %m"); + + return 0; +} + int create_shutdown_run_nologin_or_warn(void) { int r; diff --git a/src/shared/reboot-util.h b/src/shared/reboot-util.h index eaa6614df05..4548903a4c3 100644 --- a/src/shared/reboot-util.h +++ b/src/shared/reboot-util.h @@ -26,5 +26,6 @@ int reboot_with_parameter(RebootFlags flags); bool shall_restore_state(void); bool kexec_loaded(void); +int kexec(void); int create_shutdown_run_nologin_or_warn(void); diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c index fc6df238bed..73c6dd6d870 100644 --- a/src/shutdown/shutdown.c +++ b/src/shutdown/shutdown.c @@ -609,23 +609,9 @@ int main(int argc, char *argv[]) { case LINUX_REBOOT_CMD_KEXEC: if (!in_container) { - /* We cheat and exec kexec to avoid doing all its work */ log_info("Rebooting with kexec."); - r = pidref_safe_fork( - "(sd-kexec)", - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, - /* ret= */ NULL); - if (r == 0) { - /* Child */ - - (void) execl(KEXEC, KEXEC, "-e", NULL); - log_debug_errno(errno, "Failed to execute '" KEXEC "' binary, proceeding with reboot(RB_KEXEC): %m"); - - /* execv failed (kexec binary missing?), so try simply reboot(RB_KEXEC) */ - (void) reboot(cmd); - _exit(EXIT_FAILURE); - } + (void) kexec(); /* If we are still running, then the kexec can't have worked, let's fall through */ }