summaryrefslogtreecommitdiff
path: root/usr.sbin/vmd/vmd.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2016-12-14 06:59:13 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2016-12-14 06:59:13 +0000
commitf36838ee92524efe7682361388be3d6802392210 (patch)
tree37ece3aec692312b8e1f576ee5a15f7d8feb4d68 /usr.sbin/vmd/vmd.c
parent289324f1e12ade78d6ad882848c687c91268a838 (diff)
If a VM terminates with the result EAGAIN, close all fds except the
pty and re-send it to the vmm monitor process. With additional changes in vmm.c, this will allow perform a cold reboot of VM. With testing and feedback from Jon Bernard OK mlarkin@
Diffstat (limited to 'usr.sbin/vmd/vmd.c')
-rw-r--r--usr.sbin/vmd/vmd.c59
1 files changed, 48 insertions, 11 deletions
diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c
index 44fe0ddae37..d572784bb05 100644
--- a/usr.sbin/vmd/vmd.c
+++ b/usr.sbin/vmd/vmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.c,v 1.45 2016/11/26 20:03:42 reyk Exp $ */
+/* $OpenBSD: vmd.c,v 1.46 2016/12/14 06:59:12 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -203,17 +203,29 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct imsg *imsg)
vcp->vcp_name, vcp->vcp_id, vm->vm_ttyname);
break;
case IMSG_VMDOP_TERMINATE_VM_RESPONSE:
- case IMSG_VMDOP_TERMINATE_VM_EVENT:
IMSG_SIZE_CHECK(imsg, &vmr);
memcpy(&vmr, imsg->data, sizeof(vmr));
- if (imsg->hdr.type == IMSG_VMDOP_TERMINATE_VM_RESPONSE)
- proc_forward_imsg(ps, imsg, PROC_CONTROL, -1);
+ proc_forward_imsg(ps, imsg, PROC_CONTROL, -1);
if (vmr.vmr_result == 0) {
/* Remove local reference */
vm = vm_getbyid(vmr.vmr_id);
vm_remove(vm);
}
break;
+ case IMSG_VMDOP_TERMINATE_VM_EVENT:
+ IMSG_SIZE_CHECK(imsg, &vmr);
+ memcpy(&vmr, imsg->data, sizeof(vmr));
+ if ((vm = vm_getbyid(vmr.vmr_id)) == NULL)
+ break;
+ if (vmr.vmr_result == 0) {
+ /* Remove local reference */
+ vm_remove(vm);
+ } else if (vmr.vmr_result == EAGAIN) {
+ /* Stop VM instance but keep the tty open */
+ vm_stop(vm, 1);
+ config_setvm(ps, vm, (uint32_t)-1);
+ }
+ break;
case IMSG_VMDOP_GET_INFO_VM_DATA:
IMSG_SIZE_CHECK(imsg, &vir);
memcpy(&vir, imsg->data, sizeof(vir));
@@ -615,32 +627,57 @@ vm_getbypid(pid_t pid)
}
void
-vm_remove(struct vmd_vm *vm)
+vm_stop(struct vmd_vm *vm, int keeptty)
{
unsigned int i;
if (vm == NULL)
return;
- TAILQ_REMOVE(env->vmd_vms, vm, vm_entry);
+ vm->vm_running = 0;
for (i = 0; i < VMM_MAX_DISKS_PER_VM; i++) {
- if (vm->vm_disks[i] != -1)
+ if (vm->vm_disks[i] != -1) {
close(vm->vm_disks[i]);
+ vm->vm_disks[i] = -1;
+ }
}
for (i = 0; i < VMM_MAX_NICS_PER_VM; i++) {
- if (vm->vm_ifs[i].vif_fd != -1)
+ if (vm->vm_ifs[i].vif_fd != -1) {
close(vm->vm_ifs[i].vif_fd);
+ vm->vm_ifs[i].vif_fd = -1;
+ }
free(vm->vm_ifs[i].vif_name);
free(vm->vm_ifs[i].vif_switch);
free(vm->vm_ifs[i].vif_group);
+ vm->vm_ifs[i].vif_name = NULL;
+ vm->vm_ifs[i].vif_switch = NULL;
+ vm->vm_ifs[i].vif_group = NULL;
}
- if (vm->vm_kernel != -1)
+ if (vm->vm_kernel != -1) {
close(vm->vm_kernel);
- if (vm->vm_tty != -1)
- close(vm->vm_tty);
+ vm->vm_kernel = -1;
+ }
+
+ if (keeptty)
+ return;
+ if (vm->vm_tty != -1) {
+ close(vm->vm_tty);
+ vm->vm_tty = -1;
+ }
free(vm->vm_ttyname);
+ vm->vm_ttyname = NULL;
+}
+
+void
+vm_remove(struct vmd_vm *vm)
+{
+ if (vm == NULL)
+ return;
+
+ TAILQ_REMOVE(env->vmd_vms, vm, vm_entry);
+ vm_stop(vm, 0);
free(vm);
}