#include "qemu_domain.h"
#include "qemu_process.h"
#include "qemu_extdevice.h"
+#include "qemu_hostdev.h"
#include "virlog.h"
#include "viralloc.h"
#include "virerror.h"
}
+/**
+ * qemuSetupHostdevCgroup:
+ * vm: domain object
+ * @dev: device to allow
+ *
+ * For given host device @dev allow access to in Cgroups.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise.
+ */
int
qemuSetupHostdevCgroup(virDomainObjPtr vm,
virDomainHostdevDefPtr dev)
goto cleanup;
}
+ if (qemuHostdevNeedsVFIO(dev)) {
+ VIR_DEBUG("Cgroup allow %s perms=%d", QEMU_DEV_VFIO, VIR_CGROUP_DEVICE_RW);
+ rv = virCgroupAllowDevicePath(priv->cgroup, QEMU_DEV_VFIO,
+ VIR_CGROUP_DEVICE_RW, false);
+ virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
+ QEMU_DEV_VFIO, "rw", rv);
+ if (rv < 0)
+ goto cleanup;
+ }
+
ret = 0;
cleanup:
return ret;
}
+
+/**
+ * qemuTeardownHostdevCgroup:
+ * @vm: doamin object
+ * @dev: device to tear down
+ *
+ * For given host device @dev deny access to it in CGroups.
+ * Note, @dev must not be in @vm's definition.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise.
+ */
int
qemuTeardownHostdevCgroup(virDomainObjPtr vm,
- virDomainHostdevDefPtr dev)
+ virDomainHostdevDefPtr dev)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
char **path = NULL;
goto cleanup;
}
+ if (qemuHostdevNeedsVFIO(dev) &&
+ !qemuDomainNeedsVFIO(vm->def)) {
+ VIR_DEBUG("Cgroup deny " QEMU_DEV_VFIO);
+ rv = virCgroupDenyDevicePath(priv->cgroup, QEMU_DEV_VFIO,
+ VIR_CGROUP_DEVICE_RWM, false);
+ virDomainAuditCgroupPath(vm, priv->cgroup, "deny",
+ QEMU_DEV_VFIO, "rwm", rv);
+ if (rv < 0)
+ goto cleanup;
+ }
+
ret = 0;
cleanup:
for (i = 0; i < npaths; i++)
goto cleanup;
for (i = 0; i < vm->def->nhostdevs; i++) {
+ /* This may allow /dev/vfio/vfio multiple times, but that
+ * is not a problem. Kernel will have only one record. */
if (qemuSetupHostdevCgroup(vm, vm->def->hostdevs[i]) < 0)
goto cleanup;
}
goto cleanup;
}
+ if (qemuHostdevNeedsVFIO(dev) &&
+ qemuDomainCreateDevice(QEMU_DEV_VFIO, data, false) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
for (i = 0; i < npaths; i++)
}
+/**
+ * qemuDomainNamespaceSetupHostdev:
+ * @vm: domain object
+ * @hostdev: hostdev to create in @vm's namespace
+ *
+ * For given @hostdev, create its devfs representation (if it has one) in
+ * domain namespace. Note, @hostdev must not be in @vm's definition.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise.
+ */
int
qemuDomainNamespaceSetupHostdev(virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
if (qemuDomainNamespaceMknodPaths(vm, (const char **)paths, npaths) < 0)
goto cleanup;
+ if (qemuHostdevNeedsVFIO(hostdev) &&
+ !qemuDomainNeedsVFIO(vm->def) &&
+ qemuDomainNamespaceMknodPath(vm, QEMU_DEV_VFIO) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
for (i = 0; i < npaths; i++)
}
+/**
+ * qemuDomainNamespaceTeardownHostdev:
+ * @vm: domain object
+ * @hostdev: hostdev to remove in @vm's namespace
+ *
+ * For given @hostdev, remove its devfs representation (if it has one) in
+ * domain namespace. Note, @hostdev must not be in @vm's definition.
+ *
+ * Returns: 0 on success,
+ * -1 otherwise.
+ */
int
qemuDomainNamespaceTeardownHostdev(virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
if (qemuDomainNamespaceUnlinkPaths(vm, (const char **)paths, npaths) < 0)
goto cleanup;
+ if (qemuHostdevNeedsVFIO(hostdev) &&
+ !qemuDomainNeedsVFIO(vm->def) &&
+ qemuDomainNamespaceUnlinkPath(vm, QEMU_DEV_VFIO) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
for (i = 0; i < npaths; i++)