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.
This commit is contained in:
committed by
Daan De Meyer
parent
5f2258affc
commit
1224e5d195
@@ -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.",
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
-15
@@ -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 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user