Mediated devices support hot-{plug,unplug} since their introduction in
kernel 4.10, however this feature has been missing in libvirt since
commit ec783d7c introduced a hostdev type for mdevs.
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
src/qemu/qemu_hotplug.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 6ec401e21..4abc7393b 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2567,6 +2567,88 @@ qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver,
}
+static int
+qemuDomainAttachMediatedDevice(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainHostdevDefPtr hostdev)
+{
+ int ret = -1;
+ char *devstr = NULL;
+ bool added = false;
+ bool teardowncgroup = false;
+ bool teardownlabel = false;
+ bool teardowndevice = false;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
+ { .hostdev = hostdev } };
+
+ if (qemuDomainEnsurePCIAddress(vm, &dev, driver) < 0)
+ return -1;
+
+ if (qemuHostdevPrepareMediatedDevices(driver,
+ vm->def->name,
+ &hostdev,
+ 1) < 0)
+ goto cleanup;
+ added = true;
+
+ if (qemuDomainNamespaceSetupHostdev(vm, hostdev) < 0)
+ goto cleanup;
+ teardowndevice = true;
+
+ if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
+ goto cleanup;
+ teardowncgroup = true;
+
+ if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
+ goto cleanup;
+ teardownlabel = true;
+
+ if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1)
< 0)
+ goto cleanup;
+
+ if (!(devstr = qemuBuildHostdevMediatedDevStr(vm->def, hostdev,
+ priv->qemuCaps)))
+ goto cleanup;
+
+ if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0)
+ goto cleanup;
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ ret = qemuMonitorAddDevice(priv->mon, devstr);
+ if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ virDomainAuditHostdev(vm, hostdev, "attach", ret == 0);
+ if (ret < 0)
+ goto cleanup;
+
+ VIR_APPEND_ELEMENT_INPLACE(vm->def->hostdevs, vm->def->nhostdevs,
hostdev);
+ ret = 0;
+ cleanup:
+ if (ret < 0) {
+ if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+ VIR_WARN("Unable to remove host device cgroup ACL on hotplug
fail");
+ if (teardownlabel &&
+ qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
+ VIR_WARN("Unable to restore host device labelling on hotplug
fail");
+ if (teardowndevice &&
+ qemuDomainNamespaceTeardownHostdev(vm, hostdev) < 0)
+ VIR_WARN("Unable to remove host device from /dev");
+ if (added)
+ qemuHostdevReAttachMediatedDevices(driver,
+ vm->def->name,
+ vm->def->hostdevs,
+ vm->def->nhostdevs);
+ qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
+ }
+ VIR_FREE(devstr);
+ return ret;
+}
+
+
int
qemuDomainAttachHostDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -2602,6 +2684,10 @@ qemuDomainAttachHostDevice(virQEMUDriverPtr driver,
if (qemuDomainAttachSCSIVHostDevice(driver, vm, hostdev) < 0)
goto error;
break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
+ if (qemuDomainAttachMediatedDevice(driver, vm, hostdev) < 0)
+ goto error;
+ break;
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
--
2.14.3