diff options
author | Mike Larkin <mlarkin@cvs.openbsd.org> | 2017-09-08 07:08:50 +0000 |
---|---|---|
committer | Mike Larkin <mlarkin@cvs.openbsd.org> | 2017-09-08 07:08:50 +0000 |
commit | e3efaa870f229905a8fd1a2c03eec8254e36ccce (patch) | |
tree | b1d8bb63fb22f9686294e4a436e7181ebac67f53 | |
parent | 9b1f7edb614f52c99e353fc494bdb3d6570930c0 (diff) |
better VM termination handling.
diff provided by Carlos Cardenas, thanks
-rw-r--r-- | usr.sbin/vmctl/vmctl.c | 18 | ||||
-rw-r--r-- | usr.sbin/vmd/vmd.h | 3 | ||||
-rw-r--r-- | usr.sbin/vmd/vmm.c | 65 |
3 files changed, 57 insertions, 29 deletions
diff --git a/usr.sbin/vmctl/vmctl.c b/usr.sbin/vmctl/vmctl.c index a580b31f48b..c6cd8e3dc8a 100644 --- a/usr.sbin/vmctl/vmctl.c +++ b/usr.sbin/vmctl/vmctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmctl.c,v 1.43 2017/09/08 06:43:47 mlarkin Exp $ */ +/* $OpenBSD: vmctl.c,v 1.44 2017/09/08 07:08:49 mlarkin Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> @@ -439,12 +439,19 @@ terminate_vm_complete(struct imsg *imsg, int *ret) vmr = (struct vmop_result *)imsg->data; res = vmr->vmr_result; if (res) { - errno = res; - if (res == ENOENT) + switch (res) { + case VMD_VM_STOP_INVALID: + warnx("cannot stop vm that is not running"); + *ret = EINVAL; + break; + case ENOENT: warnx("vm not found"); - else + *ret = EIO; + break; + default: warn("terminate vm command failed"); - *ret = EIO; + *ret = EIO; + } } else { warnx("sent request to terminate vm %d", vmr->vmr_id); *ret = 0; @@ -453,6 +460,7 @@ terminate_vm_complete(struct imsg *imsg, int *ret) warnx("unexpected response received from vmd"); *ret = EINVAL; } + errno = *ret; return (1); } diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index 22da6d58a7b..c74e3511af4 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.h,v 1.61 2017/08/31 06:23:37 mlarkin Exp $ */ +/* $OpenBSD: vmd.h,v 1.62 2017/09/08 07:08:49 mlarkin Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -54,6 +54,7 @@ #define VMD_BIOS_MISSING 1001 #define VMD_DISK_MISSING 1002 #define VMD_DISK_INVALID 1003 +#define VMD_VM_STOP_INVALID 1004 /* 100.64.0.0/10 from rfc6598 (IPv4 Prefix for Shared Address Space) */ #define VMD_DHCP_PREFIX "100.64.0.0/10" diff --git a/usr.sbin/vmd/vmm.c b/usr.sbin/vmd/vmm.c index 601dfd612fd..00b0b1f1d7b 100644 --- a/usr.sbin/vmd/vmm.c +++ b/usr.sbin/vmd/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.74 2017/09/08 06:56:54 mlarkin Exp $ */ +/* $OpenBSD: vmm.c,v 1.75 2017/09/08 07:08:49 mlarkin Exp $ */ /* * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org> @@ -150,29 +150,45 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) if (id == 0) { res = ENOENT; - } else if ((vm = vm_getbyvmid(id)) != NULL && - vm->vm_shutdown == 0) { - log_debug("%s: sending shutdown request to vm %d", - __func__, id); - - /* - * Request reboot but mark the VM as shutting down. - * This way we can terminate the VM after the triple - * fault instead of reboot and avoid being stuck in - * the ACPI-less powerdown ("press any key to reboot") - * of the VM. - */ - vm->vm_shutdown = 1; - if (imsg_compose_event(&vm->vm_iev, - IMSG_VMDOP_VM_REBOOT, 0, 0, -1, NULL, 0) == -1) - res = errno; - else - res = 0; + } else if ((vm = vm_getbyvmid(id)) != NULL) { + if (vm->vm_shutdown == 0) { + log_debug("%s: sending shutdown req to vm %d", + __func__, id); + + /* + * Request reboot but mark the VM as shutting + * down. This way we can terminate the VM after + * the triple fault instead of reboot and + * avoid being stuck in the ACPI-less powerdown + * ("press any key to reboot") of the VM. + */ + vm->vm_shutdown = 1; + if (imsg_compose_event(&vm->vm_iev, + IMSG_VMDOP_VM_REBOOT, + 0, 0, -1, NULL, 0) == -1) + res = errno; + else + res = 0; + } else { + /* in the process of shutting down... */ + log_debug("%s: performing a forced shutdown", + __func__); + vtp.vtp_vm_id = vm_vmid2id(vm->vm_vmid, vm); + /* ensure vm_id isn't 0 */ + if (vtp.vtp_vm_id != 0) { + res = terminate_vm(&vtp); + vm_remove(vm); + } else { + log_debug("%s: no vm running anymore", + __func__); + res = VMD_VM_STOP_INVALID; + } + } } else { - /* Terminate VMs that are unknown or shutting down */ - vtp.vtp_vm_id = vm_vmid2id(vm->vm_vmid, vm); - res = terminate_vm(&vtp); - vm_remove(vm); + /* vm doesn't exist, cannot stop vm */ + log_debug("%s: cannot stop vm that is not running", + __func__); + res = VMD_VM_STOP_INVALID; } cmd = IMSG_VMDOP_TERMINATE_VM_RESPONSE; break; @@ -346,6 +362,8 @@ vmm_sighdlr(int sig, short event, void *arg) vmid = vm->vm_params.vmc_params.vcp_id; vtp.vtp_vm_id = vmid; + log_debug("%s: attempting to terminate vm %d", + __func__, vm->vm_vmid); if (terminate_vm(&vtp) == 0) { memset(&vmr, 0, sizeof(vmr)); vmr.vmr_result = ret; @@ -515,6 +533,7 @@ vmm_dispatch_vm(int fd, short event, void *arg) int terminate_vm(struct vm_terminate_params *vtp) { + log_debug("%s: terminating vmid %d", __func__, vtp->vtp_vm_id); if (ioctl(env->vmd_fd, VMM_IOC_TERM, vtp) < 0) return (errno); |