summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Larkin <mlarkin@cvs.openbsd.org>2017-09-08 07:08:50 +0000
committerMike Larkin <mlarkin@cvs.openbsd.org>2017-09-08 07:08:50 +0000
commite3efaa870f229905a8fd1a2c03eec8254e36ccce (patch)
treeb1d8bb63fb22f9686294e4a436e7181ebac67f53
parent9b1f7edb614f52c99e353fc494bdb3d6570930c0 (diff)
better VM termination handling.
diff provided by Carlos Cardenas, thanks
-rw-r--r--usr.sbin/vmctl/vmctl.c18
-rw-r--r--usr.sbin/vmd/vmd.h3
-rw-r--r--usr.sbin/vmd/vmm.c65
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);