"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
- "/dev/rtc", "/dev/hpet",
+ "/dev/rtc", "/dev/hpet", "/dev/vfio/vfio",
NULL,
};
#define DEVICE_PTY_MAJOR 136
}
+int
+qemuSetupHostdevCGroup(virDomainObjPtr vm,
+ virDomainHostdevDefPtr dev)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virPCIDevicePtr pci = NULL;
+ char *path = NULL;
+
+ /* currently this only does something for PCI devices using vfio
+ * for device assignment, but it is called for *all* hostdev
+ * devices.
+ */
+
+ if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
+ return 0;
+
+ if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
+
+ switch (dev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ if (dev->source.subsys.u.pci.backend
+ != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+ int rc;
+
+ pci = virPCIDeviceNew(dev->source.subsys.u.pci.addr.domain,
+ dev->source.subsys.u.pci.addr.bus,
+ dev->source.subsys.u.pci.addr.slot,
+ dev->source.subsys.u.pci.addr.function);
+ if (!pci)
+ goto cleanup;
+
+ if (!(path = virPCIDeviceGetVFIOGroupDev(pci)))
+ goto cleanup;
+
+ VIR_DEBUG("Cgroup allow %s for PCI device assignment", path);
+ rc = virCgroupAllowDevicePath(priv->cgroup, path,
+ VIR_CGROUP_DEVICE_RW);
+ virDomainAuditCgroupPath(vm, priv->cgroup,
+ "allow", path, "rw", rc);
+ if (rc < 0) {
+ virReportSystemError(-rc,
+ _("Unable to allow access "
+ "for device path %s"),
+ path);
+ goto cleanup;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ret = 0;
+cleanup:
+ virPCIDeviceFree(pci);
+ VIR_FREE(path);
+ return ret;
+}
+
+
+
+int
+qemuTeardownHostdevCgroup(virDomainObjPtr vm,
+ virDomainHostdevDefPtr dev)
+{
+ int ret = -1;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virPCIDevicePtr pci = NULL;
+ char *path = NULL;
+
+ /* currently this only does something for PCI devices using vfio
+ * for device assignment, but it is called for *all* hostdev
+ * devices.
+ */
+
+ if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
+ return 0;
+
+ if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
+
+ switch (dev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ if (dev->source.subsys.u.pci.backend
+ != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+ int rc;
+
+ pci = virPCIDeviceNew(dev->source.subsys.u.pci.addr.domain,
+ dev->source.subsys.u.pci.addr.bus,
+ dev->source.subsys.u.pci.addr.slot,
+ dev->source.subsys.u.pci.addr.function);
+ if (!pci)
+ goto cleanup;
+
+ if (!(path = virPCIDeviceGetVFIOGroupDev(pci)))
+ goto cleanup;
+
+ VIR_DEBUG("Cgroup deny %s for PCI device assignment", path);
+ rc = virCgroupDenyDevicePath(priv->cgroup, path,
+ VIR_CGROUP_DEVICE_RWM);
+ virDomainAuditCgroupPath(vm, priv->cgroup,
+ "deny", path, "rwm", rc);
+ if (rc < 0) {
+ virReportSystemError(-rc,
+ _("Unable to deny access "
+ "for device path %s"),
+ path);
+ goto cleanup;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ret = 0;
+cleanup:
+ virPCIDeviceFree(pci);
+ VIR_FREE(path);
+ return ret;
+}
+
+
int qemuInitCgroup(virQEMUDriverPtr driver,
virDomainObjPtr vm,
bool startup)
virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
virUSBDevicePtr usb;
+ if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+ goto cleanup;
+
+ /* NB: the code below here should be moved into
+ * qemuSetupHostdevCGroup()
+ */
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
continue;
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
/*
* qemu_cgroup.h: QEMU cgroup management
*
- * Copyright (C) 2006-2007, 2009-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2007, 2009-2013 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
int qemuSetupHostUsbDeviceCgroup(virUSBDevicePtr dev,
const char *path,
void *opaque);
+int qemuSetupHostdevCGroup(virDomainObjPtr vm,
+ virDomainHostdevDefPtr dev)
+ ATTRIBUTE_RETURN_CHECK;
+int qemuTeardownHostdevCgroup(virDomainObjPtr vm,
+ virDomainHostdevDefPtr dev)
+ ATTRIBUTE_RETURN_CHECK;
int qemuInitCgroup(virQEMUDriverPtr driver,
virDomainObjPtr vm,
bool startup);
virUSBDeviceListSteal(list, usb);
}
+ if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+ goto cleanup;
+
if (virSecurityManagerSetHostdevLabel(driver->securityManager,
vm->def, hostdev, NULL) < 0)
- goto cleanup;
+ goto teardown_cgroup;
switch (hostdev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
vm->def, hostdev, NULL) < 0)
VIR_WARN("Unable to restore host device labelling on hotplug fail");
+teardown_cgroup:
+ if (qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+ VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
+
cleanup:
virObjectUnref(list);
if (usb)
}
if (!ret) {
+ if (qemuTeardownHostdevCgroup(vm, detach) < 0)
+ VIR_WARN("Failed to remove host device cgroup ACL");
+
if (virSecurityManagerRestoreHostdevLabel(driver->securityManager,
vm->def, detach, NULL) < 0) {
VIR_WARN("Failed to restore host device labelling");