summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorEdd Barrett <edd@cvs.openbsd.org>2016-10-29 14:56:06 +0000
committerEdd Barrett <edd@cvs.openbsd.org>2016-10-29 14:56:06 +0000
commitaa019a199102d09ac1b3afc11b4239a940cb9156 (patch)
tree5e574b20e4b14bac1b2ede34eabcf8d1fcf73cd7 /usr.sbin
parentb69b97da3a31172cf0e1eb5952528e05017b3f48 (diff)
Separate parsing vms and switches from starting them in vmd(8).
Brings us one step closer to having disabled by default vms is vm.conf(5), which can be started with vmctl(8). Input, testing and OK reyk@. Thanks.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/vmd/config.c57
-rw-r--r--usr.sbin/vmd/parse.y40
-rw-r--r--usr.sbin/vmd/priv.c5
-rw-r--r--usr.sbin/vmd/vmd.c77
-rw-r--r--usr.sbin/vmd/vmd.h11
-rw-r--r--usr.sbin/vmd/vmm.c21
6 files changed, 145 insertions, 66 deletions
diff --git a/usr.sbin/vmd/config.c b/usr.sbin/vmd/config.c
index bda115c6f2d..2592ea23792 100644
--- a/usr.sbin/vmd/config.c
+++ b/usr.sbin/vmd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.16 2016/10/15 14:02:11 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.17 2016/10/29 14:56:05 edd Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -120,26 +120,20 @@ config_getreset(struct vmd *env, struct imsg *imsg)
}
int
-config_getvm(struct privsep *ps, struct vmop_create_params *vmc,
- int kernel_fd, uint32_t peerid)
+config_registervm(struct privsep *ps, struct vmop_create_params *vmc,
+ struct vmd_vm **ret_vm)
{
struct vmd *env = ps->ps_env;
struct vmd_vm *vm = NULL;
- struct vmd_if *vif;
struct vm_create_params *vcp = &vmc->vmc_params;
unsigned int i;
- int fd, ttys_fd;
- int kernfd = -1, *diskfds = NULL, *tapfds = NULL;
- int saved_errno = 0;
- char ptyname[VM_TTYNAME_MAX];
- char ifname[IF_NAMESIZE], *s;
- char path[PATH_MAX];
- unsigned int unit;
errno = 0;
+ *ret_vm = NULL;
- if (vm_getbyname(vcp->vcp_name) != NULL) {
- saved_errno = errno = EALREADY;
+ if ((vm = vm_getbyname(vcp->vcp_name)) != NULL) {
+ *ret_vm = vm;
+ errno = EALREADY;
goto fail;
}
@@ -159,7 +153,7 @@ config_getvm(struct privsep *ps, struct vmop_create_params *vmc,
if ((vm = calloc(1, sizeof(*vm))) == NULL)
goto fail;
- memcpy(&vm->vm_params, vcp, sizeof(vm->vm_params));
+ memcpy(&vm->vm_params, vmc, sizeof(vm->vm_params));
vm->vm_pid = -1;
for (i = 0; i < vcp->vcp_ndisks; i++)
@@ -173,6 +167,35 @@ config_getvm(struct privsep *ps, struct vmop_create_params *vmc,
fatalx("too many vms");
TAILQ_INSERT_TAIL(env->vmd_vms, vm, vm_entry);
+ env->vmd_nvm++;
+ *ret_vm = vm;
+ return (0);
+fail:
+ if (errno == 0)
+ errno = EINVAL;
+ return (-1);
+}
+
+int
+config_getvm(struct privsep *ps, struct vmd_vm *vm,
+ int kernel_fd, uint32_t peerid)
+{
+ struct vmd_if *vif;
+ struct vmop_create_params *vmc = &vm->vm_params;
+ struct vm_create_params *vcp = &vmc->vmc_params;
+ unsigned int i;
+ int fd, ttys_fd;
+ int kernfd = -1, *diskfds = NULL, *tapfds = NULL;
+ int saved_errno = 0;
+ char ptyname[VM_TTYNAME_MAX];
+ char ifname[IF_NAMESIZE], *s;
+ char path[PATH_MAX];
+ unsigned int unit;
+
+ errno = 0;
+
+ if (vm->vm_running)
+ goto fail;
switch (privsep_process) {
case PROC_VMM:
@@ -321,7 +344,7 @@ config_getvm(struct privsep *ps, struct vmop_create_params *vmc,
free(diskfds);
free(tapfds);
- env->vmd_nvm++;
+ vm->vm_running = 1;
return (0);
fail:
@@ -360,7 +383,7 @@ config_getdisk(struct privsep *ps, struct imsg *imsg)
IMSG_SIZE_CHECK(imsg, &n);
memcpy(&n, imsg->data, sizeof(n));
- if (n >= vm->vm_params.vcp_ndisks ||
+ if (n >= vm->vm_params.vmc_params.vcp_ndisks ||
vm->vm_disks[n] != -1 || imsg->fd == -1) {
log_debug("invalid disk id");
errno = EINVAL;
@@ -385,7 +408,7 @@ config_getif(struct privsep *ps, struct imsg *imsg)
IMSG_SIZE_CHECK(imsg, &n);
memcpy(&n, imsg->data, sizeof(n));
- if (n >= vm->vm_params.vcp_nnics ||
+ if (n >= vm->vm_params.vmc_params.vcp_nnics ||
vm->vm_ifs[n].vif_fd != -1 || imsg->fd == -1) {
log_debug("invalid interface id");
goto fail;
diff --git a/usr.sbin/vmd/parse.y b/usr.sbin/vmd/parse.y
index fb85b1ea0be..fe2d3b83c61 100644
--- a/usr.sbin/vmd/parse.y
+++ b/usr.sbin/vmd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.11 2016/10/17 16:26:20 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.12 2016/10/29 14:56:05 edd Exp $ */
/*
* Copyright (c) 2007-2016 Reyk Floeter <reyk@openbsd.org>
@@ -87,6 +87,7 @@ static struct vmop_create_params vmc;
static struct vm_create_params *vcp;
static struct vmd_switch *vsw;
static struct vmd_if *vif;
+static struct vmd_vm *vm;
static unsigned int vsw_unit;
static char vsw_type[IF_NAMESIZE];
static int vcp_disable;
@@ -173,30 +174,15 @@ switch : SWITCH string {
vcp_disable = 0;
} '{' optnl switch_opts_l '}' {
- TAILQ_INSERT_TAIL(env->vmd_switches, vsw, sw_entry);
- env->vmd_nswitches++;
-
if (vcp_disable) {
log_debug("%s:%d: switch \"%s\""
" skipped (disabled)",
file->name, yylval.lineno, vsw->sw_name);
} else if (!env->vmd_noaction) {
- /*
- * XXX Configure the switch right away -
- * XXX this should be done after parsing
- * XXX the configuration.
- */
- if (vm_priv_brconfig(&env->vmd_ps, vsw) == -1) {
- log_warn("%s:%d: switch \"%s\" failed",
- file->name, yylval.lineno,
- vsw->sw_name);
- YYERROR;
- } else {
- log_debug("%s:%d: switch \"%s\""
- " configured",
- file->name, yylval.lineno,
- vsw->sw_name);
- }
+ TAILQ_INSERT_TAIL(env->vmd_switches, vsw, sw_entry);
+ env->vmd_nswitches++;
+ log_debug("%s:%d: switch \"%s\" registered",
+ file->name, yylval.lineno, vsw->sw_name);
}
}
;
@@ -285,24 +271,20 @@ vm : VM string {
log_debug("%s:%d: vm \"%s\" skipped (disabled)",
file->name, yylval.lineno, vcp->vcp_name);
} else if (!env->vmd_noaction) {
- /*
- * XXX Start the vm right away -
- * XXX this should be done after parsing
- * XXX the configuration.
- */
- ret = config_getvm(&env->vmd_ps, &vmc, -1, -1);
+ ret = config_registervm(&env->vmd_ps, &vmc, &vm);
if (ret == -1 && errno == EALREADY) {
log_debug("%s:%d: vm \"%s\""
- " skipped (running)",
+ " skipped (%s)",
file->name, yylval.lineno,
- vcp->vcp_name);
+ vcp->vcp_name, vm->vm_running ?
+ "running" : "already exists");
} else if (ret == -1) {
log_warn("%s:%d: vm \"%s\" failed",
file->name, yylval.lineno,
vcp->vcp_name);
YYERROR;
} else {
- log_debug("%s:%d: vm \"%s\" enabled",
+ log_debug("%s:%d: vm \"%s\" registered",
file->name, yylval.lineno,
vcp->vcp_name);
}
diff --git a/usr.sbin/vmd/priv.c b/usr.sbin/vmd/priv.c
index f28e3acaf87..50cba913289 100644
--- a/usr.sbin/vmd/priv.c
+++ b/usr.sbin/vmd/priv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: priv.c,v 1.4 2016/10/17 16:26:20 reyk Exp $ */
+/* $OpenBSD: priv.c,v 1.5 2016/10/29 14:56:05 edd Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -222,7 +222,7 @@ priv_validgroup(const char *name)
int
vm_priv_ifconfig(struct privsep *ps, struct vmd_vm *vm)
{
- struct vm_create_params *vcp = &vm->vm_params;
+ struct vm_create_params *vcp = &vm->vm_params.vmc_params;
struct vmd_if *vif;
struct vmd_switch *vsw;
unsigned int i;
@@ -343,5 +343,6 @@ vm_priv_brconfig(struct privsep *ps, struct vmd_switch *vsw)
IMSG_VMDOP_PRIV_IFUP : IMSG_VMDOP_PRIV_IFDOWN,
&vfr, sizeof(vfr));
+ vsw->sw_running = 1;
return (0);
}
diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c
index de4a41b1847..481b35364f4 100644
--- a/usr.sbin/vmd/vmd.c
+++ b/usr.sbin/vmd/vmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.c,v 1.36 2016/10/17 16:26:20 reyk Exp $ */
+/* $OpenBSD: vmd.c,v 1.37 2016/10/29 14:56:05 edd Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -77,10 +77,17 @@ vmd_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
case IMSG_VMDOP_START_VM_REQUEST:
IMSG_SIZE_CHECK(imsg, &vmc);
memcpy(&vmc, imsg->data, sizeof(vmc));
- res = config_getvm(ps, &vmc, -1, imsg->hdr.peerid);
+ res = config_registervm(ps, &vmc, &vm);
if (res == -1) {
res = errno;
cmd = IMSG_VMDOP_START_VM_RESPONSE;
+ } else {
+ res = config_getvm(ps, vm, -1, imsg->hdr.peerid);
+ if (res == -1) {
+ res = errno;
+ cmd = IMSG_VMDOP_START_VM_RESPONSE;
+ vm_remove(vm);
+ }
}
break;
case IMSG_VMDOP_TERMINATE_VM_REQUEST:
@@ -93,7 +100,7 @@ vmd_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
cmd = IMSG_VMDOP_TERMINATE_VM_RESPONSE;
break;
}
- id = vm->vm_params.vcp_id;
+ id = vm->vm_params.vmc_params.vcp_id;
}
memset(&vtp, 0, sizeof(vtp));
vtp.vtp_vm_id = id;
@@ -160,7 +167,7 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct imsg *imsg)
if ((vm = vm_getbyvmid(imsg->hdr.peerid)) == NULL)
fatalx("%s: invalid vm response", __func__);
vm->vm_pid = vmr.vmr_pid;
- vcp = &vm->vm_params;
+ vcp = &vm->vm_params.vmc_params;
vcp->vcp_id = vmr.vmr_id;
/*
@@ -419,6 +426,10 @@ main(int argc, char **argv)
int
vmd_configure(void)
{
+ struct vmd_vm *vm;
+ struct vmd_switch *vsw;
+ int res, ret = 0;
+
/*
* pledge in the parent process:
* stdio - for malloc and basic I/O including events.
@@ -442,12 +453,38 @@ vmd_configure(void)
exit(0);
}
- return (0);
+ TAILQ_FOREACH(vsw, env->vmd_switches, sw_entry) {
+ if (vsw->sw_running)
+ continue;
+ if (vm_priv_brconfig(&env->vmd_ps, vsw) == -1) {
+ log_warn("%s: failed to create switch %s",
+ __func__, vsw->sw_name);
+ switch_remove(vsw);
+ }
+ }
+
+ TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) {
+ res = config_getvm(&env->vmd_ps, vm, -1, -1);
+ if (res == -1) {
+ log_warn("%s: failed to create vm %s",
+ __func__,
+ vm->vm_params.vmc_params.vcp_name);
+ ret = -1;
+ vm_remove(vm);
+ goto fail;
+ }
+ }
+ fail:
+ return (ret);
}
void
vmd_reload(unsigned int reset, const char *filename)
{
+ struct vmd_vm *vm;
+ struct vmd_switch *vsw;
+ int res;
+
/* Switch back to the default config file */
if (filename == NULL || *filename == '\0')
filename = env->vmd_conffile;
@@ -464,6 +501,32 @@ vmd_reload(unsigned int reset, const char *filename)
log_debug("%s: failed to load config file %s",
__func__, filename);
}
+
+ TAILQ_FOREACH(vsw, env->vmd_switches, sw_entry) {
+ if (vsw->sw_running)
+ continue;
+ if (vm_priv_brconfig(&env->vmd_ps, vsw) == -1) {
+ log_warn("%s: failed to create switch %s",
+ __func__, vsw->sw_name);
+ switch_remove(vsw);
+ }
+ }
+
+ TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) {
+ if (vm->vm_running == 0) {
+ res = config_getvm(&env->vmd_ps, vm, -1, -1);
+ if (res == -1) {
+ log_warn("%s: failed to create vm %s",
+ __func__,
+ vm->vm_params.vmc_params.vcp_name);
+ vm_remove(vm);
+ }
+ } else {
+ log_debug("%s: not creating vm \"%s\": "
+ "(running)", __func__,
+ vm->vm_params.vmc_params.vcp_name);
+ }
+ }
}
}
@@ -496,7 +559,7 @@ vm_getbyid(uint32_t id)
struct vmd_vm *vm;
TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) {
- if (vm->vm_params.vcp_id == id)
+ if (vm->vm_params.vmc_params.vcp_id == id)
return (vm);
}
@@ -511,7 +574,7 @@ vm_getbyname(const char *name)
if (name == NULL)
return (NULL);
TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) {
- if (strcmp(vm->vm_params.vcp_name, name) == 0)
+ if (strcmp(vm->vm_params.vmc_params.vcp_name, name) == 0)
return (vm);
}
diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h
index f3cf13f5ac7..306c602ca77 100644
--- a/usr.sbin/vmd/vmd.h
+++ b/usr.sbin/vmd/vmd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.h,v 1.31 2016/10/17 16:26:20 reyk Exp $ */
+/* $OpenBSD: vmd.h,v 1.32 2016/10/29 14:56:05 edd Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -120,12 +120,13 @@ struct vmd_switch {
char *sw_group;
unsigned int sw_flags;
struct viflist sw_ifs;
+ int sw_running;
TAILQ_ENTRY(vmd_switch) sw_entry;
};
TAILQ_HEAD(switchlist, vmd_switch);
struct vmd_vm {
- struct vm_create_params vm_params;
+ struct vmop_create_params vm_params;
pid_t vm_pid;
uint32_t vm_vmid;
int vm_kernel;
@@ -134,6 +135,7 @@ struct vmd_vm {
char *vm_ttyname;
int vm_tty;
uint32_t vm_peerid;
+ int vm_running;
TAILQ_ENTRY(vmd_vm) vm_entry;
};
TAILQ_HEAD(vmlist, vmd_vm);
@@ -189,8 +191,9 @@ int config_init(struct vmd *);
void config_purge(struct vmd *, unsigned int);
int config_setreset(struct vmd *, unsigned int);
int config_getreset(struct vmd *, struct imsg *);
-int config_getvm(struct privsep *, struct vmop_create_params *,
- int, uint32_t);
+int config_registervm(struct privsep *, struct vmop_create_params *,
+ struct vmd_vm **);
+int config_getvm(struct privsep *, struct vmd_vm *, int, uint32_t);
int config_getdisk(struct privsep *, struct imsg *);
int config_getif(struct privsep *, struct imsg *);
diff --git a/usr.sbin/vmd/vmm.c b/usr.sbin/vmd/vmm.c
index c7ff4ec9bd2..f1abde3698e 100644
--- a/usr.sbin/vmd/vmm.c
+++ b/usr.sbin/vmd/vmm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmm.c,v 1.52 2016/10/26 05:26:36 mlarkin Exp $ */
+/* $OpenBSD: vmm.c,v 1.53 2016/10/29 14:56:05 edd Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -191,10 +191,17 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
case IMSG_VMDOP_START_VM_REQUEST:
IMSG_SIZE_CHECK(imsg, &vmc);
memcpy(&vmc, imsg->data, sizeof(vmc));
- res = config_getvm(ps, &vmc, imsg->fd, imsg->hdr.peerid);
+ res = config_registervm(ps, &vmc, &vm);
if (res == -1) {
res = errno;
cmd = IMSG_VMDOP_START_VM_RESPONSE;
+ } else {
+ res = config_getvm(ps, vm, imsg->fd, imsg->hdr.peerid);
+ if (res == -1) {
+ res = errno;
+ cmd = IMSG_VMDOP_START_VM_RESPONSE;
+ vm_remove(vm);
+ }
}
break;
case IMSG_VMDOP_START_VM_DISK:
@@ -302,7 +309,7 @@ vmm_sighdlr(int sig, short event, void *arg)
continue;
}
- vmid = vm->vm_params.vcp_id;
+ vmid = vm->vm_params.vmc_params.vcp_id;
vtp.vtp_vm_id = vmid;
if (terminate_vm(&vtp) == 0) {
memset(&vmr, 0, sizeof(vmr));
@@ -339,7 +346,7 @@ vmm_shutdown(void)
struct vmd_vm *vm, *vm_next;
TAILQ_FOREACH_SAFE(vm, env->vmd_vms, vm_entry, vm_next) {
- vtp.vtp_vm_id = vm->vm_params.vcp_id;
+ vtp.vtp_vm_id = vm->vm_params.vmc_params.vcp_id;
/* XXX suspend or request graceful shutdown */
if (terminate_vm(&vtp) == ENOENT)
@@ -474,7 +481,7 @@ start_vm(struct imsg *imsg, uint32_t *id)
ret = ENOENT;
goto err;
}
- vcp = &vm->vm_params;
+ vcp = &vm->vm_params.vmc_params;
if ((vm->vm_tty = imsg->fd) == -1) {
log_warnx("%s: can't get tty", __func__);
@@ -1456,7 +1463,7 @@ write_mem(paddr_t dst, void *buf, size_t len)
size_t n, off;
struct vm_mem_range *vmr;
- vmr = find_gpa_range(&current_vm->vm_params, dst, len);
+ vmr = find_gpa_range(&current_vm->vm_params.vmc_params, dst, len);
if (vmr == NULL) {
errno = EINVAL;
log_warn("%s: failed - invalid memory range dst = 0x%lx, "
@@ -1504,7 +1511,7 @@ read_mem(paddr_t src, void *buf, size_t len)
size_t n, off;
struct vm_mem_range *vmr;
- vmr = find_gpa_range(&current_vm->vm_params, src, len);
+ vmr = find_gpa_range(&current_vm->vm_params.vmc_params, src, len);
if (vmr == NULL) {
errno = EINVAL;
log_warn("%s: failed - invalid memory range src = 0x%lx, "