File 05e149f9-call-qemuSetupHostdevCGroup-later.patch of Package libvirt.4601

commit 05e149f94cbd34e4c3d4e9c7f6871e13cfe03d8c
Author: Jiri Denemark <jdenemar@redhat.com>
Date:   Thu Nov 14 12:02:40 2013 +0100

    qemu: Call qemuSetupHostdevCGroup later during hotplug
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1025108
    
    So far qemuSetupHostdevCGroup was called very early during hotplug, even
    before we knew the device we were about to hotplug was actually
    available. By calling the function later, we make sure QEMU won't be
    allowed to access devices used by other domains.
    
    Another important effect of this change is that hopluging USB devices
    specified by vendor and product (but not by their USB address) works
    again. This was broken since v1.0.5-171-g7d763ac, when the call to
    qemuFindHostdevUSBDevice was moved after the call to
    qemuSetupHostdevCGroup, which then used an uninitialized USB address.

Index: libvirt-1.1.2/src/qemu/qemu_hotplug.c
===================================================================
--- libvirt-1.1.2.orig/src/qemu/qemu_hotplug.c
+++ libvirt-1.1.2/src/qemu/qemu_hotplug.c
@@ -1134,6 +1134,7 @@ int qemuDomainAttachHostPciDevice(virQEM
     int configfd = -1;
     char *configfd_name = NULL;
     bool releaseaddr = false;
+    bool teardowncgroup = false;
 
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
         return -1;
@@ -1164,6 +1165,10 @@ int qemuDomainAttachHostPciDevice(virQEM
         vm->def->hostdevs[vm->def->nhostdevs--] = NULL;
     }
 
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+        goto error;
+    teardowncgroup = true;
+
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
         if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
             goto error;
@@ -1220,6 +1225,9 @@ int qemuDomainAttachHostPciDevice(virQEM
     return 0;
 
 error:
+    if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
+
     if (releaseaddr)
         qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
 
@@ -1412,6 +1420,7 @@ int qemuDomainAttachHostUsbDevice(virQEM
     virUSBDevicePtr usb = NULL;
     char *devstr = NULL;
     bool added = false;
+    bool teardowncgroup = false;
     int ret = -1;
 
     if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0)
@@ -1429,6 +1438,10 @@ int qemuDomainAttachHostUsbDevice(virQEM
     added = true;
     virUSBDeviceListSteal(list, usb);
 
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+        goto cleanup;
+    teardowncgroup = true;
+
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
         if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
             goto cleanup;
@@ -1455,6 +1468,10 @@ int qemuDomainAttachHostUsbDevice(virQEM
 
     ret = 0;
 cleanup:
+    if (ret < 0 &&
+        teardowncgroup &&
+        qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
     if (added)
         virUSBDeviceListSteal(driver->activeUsbHostdevs, usb);
     virUSBDeviceFree(usb);
@@ -1472,6 +1489,7 @@ qemuDomainAttachHostScsiDevice(virQEMUDr
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char *devstr = NULL;
     char *drvstr = NULL;
+    bool teardowncgroup = false;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE) ||
         !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) ||
@@ -1492,6 +1510,10 @@ qemuDomainAttachHostScsiDevice(virQEMUDr
         return -1;
     }
 
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+        goto cleanup;
+    teardowncgroup = true;
+
     if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
         goto cleanup;
 
@@ -1529,8 +1551,11 @@ qemuDomainAttachHostScsiDevice(virQEMUDr
 
     ret = 0;
 cleanup:
-    if (ret < 0)
+    if (ret < 0) {
         qemuDomainReAttachHostScsiDevices(driver, vm->def->name, &hostdev, 1);
+        if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+            VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
+    }
     VIR_FREE(drvstr);
     VIR_FREE(devstr);
     return ret;
@@ -1547,12 +1572,9 @@ int qemuDomainAttachHostDevice(virQEMUDr
         return -1;
     }
 
-    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
-        return -1;
-
     if (virSecurityManagerSetHostdevLabel(driver->securityManager,
                                           vm->def, hostdev, NULL) < 0)
-        goto cleanup;
+        return -1;
 
     switch (hostdev->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
@@ -1586,10 +1608,6 @@ error:
     if (virSecurityManagerRestoreHostdevLabel(driver->securityManager,
                                               vm->def, hostdev, NULL) < 0)
         VIR_WARN("Unable to restore host device labelling on hotplug fail");
-
-cleanup:
-    if (qemuTeardownHostdevCgroup(vm, hostdev) < 0)
-        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
     return -1;
 }
 
openSUSE Build Service is sponsored by