Page MenuHomeFreeBSD

D53729.id166351.diff
No OneTemporary

D53729.id166351.diff

diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
--- a/lib/libvmmapi/vmmapi.h
+++ b/lib/libvmmapi/vmmapi.h
@@ -115,6 +115,7 @@
struct vmctx *vm_open(const char *name);
#define VMMAPI_OPEN_CREATE 0x01 /* create if the VM does not exist */
#define VMMAPI_OPEN_REINIT 0x02 /* reinitialize the VM if it exists */
+#define VMMAPI_OPEN_CREATE_DESTROY_ON_CLOSE 0x04 /* Destroy the VM when closing vmm_ctl */
struct vmctx *vm_openf(const char *name, int flags);
void vm_close(struct vmctx *ctx);
void vm_destroy(struct vmctx *ctx);
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -100,11 +100,13 @@
}
static int
-vm_ctl_create(const char *name, int ctlfd)
+vm_ctl_create(const char *name, int flags, int ctlfd)
{
struct vmmctl_vm_create vmc;
memset(&vmc, 0, sizeof(vmc));
+ if ((flags & VMMAPI_OPEN_CREATE_DESTROY_ON_CLOSE) != 0)
+ vmc.flags |= VMMCTL_CREATE_DESTROY_ON_CLOSE;
if (strlcpy(vmc.name, name, sizeof(vmc.name)) >= sizeof(vmc.name)) {
errno = ENAMETOOLONG;
return (-1);
@@ -121,7 +123,7 @@
if (fd < 0)
return (-1);
- error = vm_ctl_create(name, fd);
+ error = vm_ctl_create(name, 0, fd);
if (error != 0) {
error = errno;
(void)close(fd);
@@ -162,7 +164,7 @@
vm->fd = vm_device_open(vm->name);
if (vm->fd < 0 && errno == ENOENT) {
if (flags & VMMAPI_OPEN_CREATE) {
- if (vm_ctl_create(vm->name, vm->ctlfd) != 0)
+ if (vm_ctl_create(vm->name, flags, vm->ctlfd) != 0)
goto err;
vm->fd = vm_device_open(vm->name);
created = true;
diff --git a/sys/dev/vmm/vmm_dev.h b/sys/dev/vmm/vmm_dev.h
--- a/sys/dev/vmm/vmm_dev.h
+++ b/sys/dev/vmm/vmm_dev.h
@@ -70,9 +70,13 @@
#endif /* _KERNEL */
+#define VMMCTL_CREATE_DESTROY_ON_CLOSE 0x1
+#define VMMCTL_FLAGS_MASK (VMMCTL_CREATE_DESTROY_ON_CLOSE)
+
struct vmmctl_vm_create {
char name[VM_MAX_NAMELEN + 1];
- int reserved[16];
+ uint32_t flags;
+ int reserved[15];
};
struct vmmctl_vm_destroy {
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -77,10 +77,15 @@
struct cdev *cdev;
struct ucred *ucred;
SLIST_ENTRY(vmmdev_softc) link;
+ LIST_ENTRY(vmmdev_softc) priv_link;
SLIST_HEAD(, devmem_softc) devmem;
int flags;
};
+struct vmmctl_priv {
+ LIST_HEAD(, vmmdev_softc) softcs;
+};
+
static bool vmm_initialized = false;
static SLIST_HEAD(, vmmdev_softc) head;
@@ -103,6 +108,7 @@
static void devmem_destroy(void *arg);
static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *devmem);
+static void vmmdev_destroy(struct vmmdev_softc *sc);
static int
vmm_priv_check(struct ucred *ucred)
@@ -910,6 +916,8 @@
sx_xlock(&vmmdev_mtx);
SLIST_REMOVE(&head, sc, vmmdev_softc, link);
+ if ((sc->flags & VMMCTL_CREATE_DESTROY_ON_CLOSE) != 0)
+ LIST_REMOVE(sc, priv_link);
sx_xunlock(&vmmdev_mtx);
free(sc, M_VMMDEV);
}
@@ -988,12 +996,13 @@
}
static int
-vmmdev_create(const char *name, struct thread *td)
+vmmdev_create(const char *name, uint32_t flags, struct thread *td)
{
struct make_dev_args mda;
struct cdev *cdev;
struct vmmdev_softc *sc;
struct ucred *cred;
+ struct vmmctl_priv *priv;
struct vm *vm;
int error;
@@ -1002,6 +1011,11 @@
return (EINVAL);
cred = td->td_ucred;
+ flags &= VMMCTL_FLAGS_MASK;
+ error = devfs_get_cdevpriv((void **)&priv);
+ if (error)
+ return (error);
+
sx_xlock(&vmmdev_mtx);
sc = vmmdev_lookup(name, cred);
if (sc != NULL) {
@@ -1021,6 +1035,9 @@
}
sc = vmmdev_alloc(vm, cred);
SLIST_INSERT_HEAD(&head, sc, link);
+ sc->flags = flags;
+ if ((flags & VMMCTL_CREATE_DESTROY_ON_CLOSE) != 0)
+ LIST_INSERT_HEAD(&priv->softcs, sc, priv_link);
make_dev_args_init(&mda);
mda.mda_devsw = &vmmdevsw;
@@ -1037,6 +1054,7 @@
return (error);
}
sc->cdev = cdev;
+
sx_xunlock(&vmmdev_mtx);
return (0);
}
@@ -1058,7 +1076,7 @@
buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO);
error = sysctl_handle_string(oidp, buf, buflen, req);
if (error == 0 && req->newptr != NULL)
- error = vmmdev_create(buf, req->td);
+ error = vmmdev_create(buf, 0, req->td);
free(buf, M_VMMDEV);
return (error);
}
@@ -1067,10 +1085,49 @@
NULL, 0, sysctl_vmm_create, "A",
"Create a vmm(4) instance (legacy interface)");
+static void
+vmmctl_dtor(void *arg)
+{
+ struct cdev *sc_cdev;
+ struct vmmdev_softc *sc;
+ struct vmmctl_priv *priv = arg;
+
+ /*
+ * Scan the softc list for any VMs associated with
+ * the current descriptor and destroy them.
+ */
+ sx_xlock(&vmmdev_mtx);
+ while (!LIST_EMPTY(&priv->softcs)) {
+ sc = LIST_FIRST(&priv->softcs);
+ sc_cdev = sc->cdev;
+ if (sc_cdev != NULL) {
+ sc->cdev = NULL;
+ } else {
+ /*
+ * Another thread has already
+ * started the removal process.
+ */
+ }
+ /* Temporarily drop the lock to allow vmmdev_destroy to run. */
+ sx_xunlock(&vmmdev_mtx);
+ if (sc_cdev != NULL) {
+ vm_suspend(sc->vm, VM_SUSPEND_DESTROY);
+ destroy_dev(sc_cdev);
+ /* vmmdev_destroy will unlink the 'priv_link' entry. */
+ vmmdev_destroy(sc);
+ }
+ sx_xlock(&vmmdev_mtx);
+ }
+ sx_xunlock(&vmmdev_mtx);
+
+ free(priv, M_VMMDEV);
+}
+
static int
vmmctl_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
{
int error;
+ struct vmmctl_priv *priv;
error = vmm_priv_check(td->td_ucred);
if (error != 0)
@@ -1079,6 +1136,14 @@
if ((flags & FWRITE) == 0)
return (EPERM);
+ priv = malloc(sizeof(*priv), M_VMMDEV, M_WAITOK | M_ZERO);
+ LIST_INIT(&priv->softcs);
+ error = devfs_set_cdevpriv(priv, vmmctl_dtor);
+ if (error != 0) {
+ free(priv, M_VMMDEV);
+ return (error);
+ }
+
return (0);
}
@@ -1101,7 +1166,7 @@
}
}
- error = vmmdev_create(vmc->name, td);
+ error = vmmdev_create(vmc->name, vmc->flags, td);
break;
}
case VMMCTL_VM_DESTROY: {

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 13, 2:53 AM (11 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26919104
Default Alt Text
D53729.id166351.diff (5 KB)

Event Timeline