c401cc
From 4d8f410cd601aa1ff3e3eb7c4787cfa3b50c932f Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <4d8f410cd601aa1ff3e3eb7c4787cfa3b50c932f.1385135432.git.jdenemar@redhat.com>
c401cc
From: Jiri Denemark <jdenemar@redhat.com>
c401cc
Date: Fri, 15 Nov 2013 15:46:39 +0100
c401cc
Subject: [PATCH] qemu: Call qemuSetupHostdevCGroup later during hotplug
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1025108
c401cc
c401cc
So far qemuSetupHostdevCGroup was called very early during hotplug, even
c401cc
before we knew the device we were about to hotplug was actually
c401cc
available. By calling the function later, we make sure QEMU won't be
c401cc
allowed to access devices used by other domains.
c401cc
c401cc
Another important effect of this change is that hopluging USB devices
c401cc
specified by vendor and product (but not by their USB address) works
c401cc
again. This was broken since v1.0.5-171-g7d763ac, when the call to
c401cc
qemuFindHostdevUSBDevice was moved after the call to
c401cc
qemuSetupHostdevCGroup, which then used an uninitialized USB address.
c401cc
c401cc
(cherry picked from commit 05e149f94cbd34e4c3d4e9c7f6871e13cfe03d8c)
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/qemu/qemu_hotplug.c | 36 +++++++++++++++++++++++++++---------
c401cc
 1 file changed, 27 insertions(+), 9 deletions(-)
c401cc
c401cc
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
c401cc
index 4b9cc07..a60c08d 100644
c401cc
--- a/src/qemu/qemu_hotplug.c
c401cc
+++ b/src/qemu/qemu_hotplug.c
c401cc
@@ -1012,6 +1012,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
c401cc
     int configfd = -1;
c401cc
     char *configfd_name = NULL;
c401cc
     bool releaseaddr = false;
c401cc
+    bool teardowncgroup = false;
c401cc
     int backend = hostdev->source.subsys.u.pci.backend;
c401cc
 
c401cc
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0)
c401cc
@@ -1048,6 +1049,10 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
c401cc
         break;
c401cc
     }
c401cc
 
c401cc
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
c401cc
+        goto error;
c401cc
+    teardowncgroup = true;
c401cc
+
c401cc
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
c401cc
         if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
c401cc
             goto error;
c401cc
@@ -1103,6 +1108,9 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
c401cc
     return 0;
c401cc
 
c401cc
 error:
c401cc
+    if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
c401cc
+        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
c401cc
+
c401cc
     if (releaseaddr)
c401cc
         qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
c401cc
 
c401cc
@@ -1295,6 +1303,7 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
c401cc
     virUSBDevicePtr usb = NULL;
c401cc
     char *devstr = NULL;
c401cc
     bool added = false;
c401cc
+    bool teardowncgroup = false;
c401cc
     int ret = -1;
c401cc
 
c401cc
     if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0)
c401cc
@@ -1312,6 +1321,10 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
c401cc
     added = true;
c401cc
     virUSBDeviceListSteal(list, usb);
c401cc
 
c401cc
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
c401cc
+        goto cleanup;
c401cc
+    teardowncgroup = true;
c401cc
+
c401cc
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
c401cc
         if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
c401cc
             goto cleanup;
c401cc
@@ -1338,6 +1351,10 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
c401cc
 
c401cc
     ret = 0;
c401cc
 cleanup:
c401cc
+    if (ret < 0 &&
c401cc
+        teardowncgroup &&
c401cc
+        qemuTeardownHostdevCgroup(vm, hostdev) < 0)
c401cc
+        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
c401cc
     if (added)
c401cc
         virUSBDeviceListSteal(driver->activeUsbHostdevs, usb);
c401cc
     virUSBDeviceFree(usb);
c401cc
@@ -1355,6 +1372,7 @@ qemuDomainAttachHostScsiDevice(virQEMUDriverPtr driver,
c401cc
     qemuDomainObjPrivatePtr priv = vm->privateData;
c401cc
     char *devstr = NULL;
c401cc
     char *drvstr = NULL;
c401cc
+    bool teardowncgroup = false;
c401cc
 
c401cc
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE) ||
c401cc
         !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) ||
c401cc
@@ -1375,6 +1393,10 @@ qemuDomainAttachHostScsiDevice(virQEMUDriverPtr driver,
c401cc
         return -1;
c401cc
     }
c401cc
 
c401cc
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
c401cc
+        goto cleanup;
c401cc
+    teardowncgroup = true;
c401cc
+
c401cc
     if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
c401cc
         goto cleanup;
c401cc
 
c401cc
@@ -1412,8 +1434,11 @@ qemuDomainAttachHostScsiDevice(virQEMUDriverPtr driver,
c401cc
 
c401cc
     ret = 0;
c401cc
 cleanup:
c401cc
-    if (ret < 0)
c401cc
+    if (ret < 0) {
c401cc
         qemuDomainReAttachHostScsiDevices(driver, vm->def->name, &hostdev, 1);
c401cc
+        if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
c401cc
+            VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
c401cc
+    }
c401cc
     VIR_FREE(drvstr);
c401cc
     VIR_FREE(devstr);
c401cc
     return ret;
c401cc
@@ -1430,12 +1455,9 @@ int qemuDomainAttachHostDevice(virQEMUDriverPtr driver,
c401cc
         return -1;
c401cc
     }
c401cc
 
c401cc
-    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
c401cc
-        return -1;
c401cc
-
c401cc
     if (virSecurityManagerSetHostdevLabel(driver->securityManager,
c401cc
                                           vm->def, hostdev, NULL) < 0)
c401cc
-        goto cleanup;
c401cc
+        return -1;
c401cc
 
c401cc
     switch (hostdev->source.subsys.type) {
c401cc
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
c401cc
@@ -1469,10 +1491,6 @@ error:
c401cc
     if (virSecurityManagerRestoreHostdevLabel(driver->securityManager,
c401cc
                                               vm->def, hostdev, NULL) < 0)
c401cc
         VIR_WARN("Unable to restore host device labelling on hotplug fail");
c401cc
-
c401cc
-cleanup:
c401cc
-    if (qemuTeardownHostdevCgroup(vm, hostdev) < 0)
c401cc
-        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
c401cc
     return -1;
c401cc
 }
c401cc
 
c401cc
-- 
c401cc
1.8.4.4
c401cc