]> xenbits.xensource.com Git - libvirt.git/commitdiff
Reserve existing USB addresses
authorJán Tomko <jtomko@redhat.com>
Wed, 12 Aug 2015 14:52:17 +0000 (16:52 +0200)
committerJán Tomko <jtomko@redhat.com>
Thu, 21 Jul 2016 06:30:26 +0000 (08:30 +0200)
Check if they fit on the USB controllers the domain has,
and error out if two devices try to use the same address.

src/conf/domain_addr.c
src/conf/domain_addr.h
src/libvirt_private.syms
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_domain_address.c
tests/qemuxml2argvdata/qemuxml2argv-usb-hub-conflict.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c

index ad20fef14c8cb2ac2b4e2be1a02c9852cab5c844..bbac399de01de9e43439dcc9b842dbd8cc88db68 100644 (file)
@@ -1562,3 +1562,45 @@ virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
     }
     return 0;
 }
+
+
+int
+virDomainUSBAddressReserve(virDomainDeviceInfoPtr info,
+                           void *data)
+{
+    virDomainUSBAddressSetPtr addrs = data;
+    virDomainUSBAddressHubPtr targetHub = NULL;
+    char *portStr = NULL;
+    int ret = -1;
+    int targetPort;
+
+    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB)
+        return 0;
+
+    if (!virDomainUSBAddressPortIsValid(info->addr.usb.port))
+        return 0;
+
+    portStr = virDomainUSBAddressPortFormat(info->addr.usb.port);
+    if (!portStr)
+        goto cleanup;
+    VIR_DEBUG("Reserving USB address bus=%u port=%s", info->addr.usb.bus, portStr);
+
+    if (!(targetHub = virDomainUSBAddressFindPort(addrs, info, &targetPort,
+                                                  portStr)))
+        goto cleanup;
+
+    if (virBitmapIsBitSet(targetHub->portmap, targetPort)) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("Duplicate USB address bus %u port %s"),
+                       info->addr.usb.bus, portStr);
+        goto cleanup;
+    }
+
+    ignore_value(virBitmapSetBit(targetHub->portmap, targetPort));
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(portStr);
+    return ret;
+}
index 2bd4a0dfdc8ab32ec4dcad70bbf9b3046cc2b6ba..a24d2166ef863ad2620c0efcbad535e53ed701f7 100644 (file)
@@ -275,4 +275,8 @@ int virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 void virDomainUSBAddressSetFree(virDomainUSBAddressSetPtr addrs);
 
+int
+virDomainUSBAddressReserve(virDomainDeviceInfoPtr info,
+                           void *data)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 #endif /* __DOMAIN_ADDR_H__ */
index 427ba5c332253cbfdf45937756863e83421d7376..d8744aab4047cff4fe2ba6e3ea8d110007b5cfb5 100644 (file)
@@ -110,6 +110,7 @@ virDomainPCIControllerModelToConnectType;
 virDomainUSBAddressPortFormat;
 virDomainUSBAddressPortFormatBuf;
 virDomainUSBAddressPortIsValid;
+virDomainUSBAddressReserve;
 virDomainUSBAddressSetAddControllers;
 virDomainUSBAddressSetCreate;
 virDomainUSBAddressSetFree;
index 60fa592e71c4e63c63c0cb1c71d205ce7ef2e0cc..ceac22fb437158af3ad52cca75c2e3d211e63907 100644 (file)
@@ -1330,6 +1330,7 @@ qemuDomainObjPrivateFree(void *data)
     virDomainPCIAddressSetFree(priv->pciaddrs);
     virDomainCCWAddressSetFree(priv->ccwaddrs);
     virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
+    virDomainUSBAddressSetFree(priv->usbaddrs);
     virDomainChrSourceDefFree(priv->monConfig);
     qemuDomainObjFreeJob(priv);
     VIR_FREE(priv->lockState);
index 114db98db684a1ffc23e373557a12b075e8d72ad..d10ebccfd45951d661de8f72b60dec3c0ac24532 100644 (file)
@@ -187,6 +187,7 @@ struct _qemuDomainObjPrivate {
     virDomainPCIAddressSetPtr pciaddrs;
     virDomainCCWAddressSetPtr ccwaddrs;
     virDomainVirtioSerialAddrSetPtr vioserialaddrs;
+    virDomainUSBAddressSetPtr usbaddrs;
 
     virQEMUCapsPtr qemuCaps;
     char *lockState;
index ee44d45eef331032a93f42a2f1d4c392abaa10fa..f66b2f09da567628c759e62163c37c294b968e50 100644 (file)
@@ -1622,11 +1622,44 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
 }
 
 
+static int
+qemuDomainAssignUSBAddresses(virDomainDefPtr def,
+                             virDomainObjPtr obj)
+{
+    int ret = -1;
+    virDomainUSBAddressSetPtr addrs = NULL;
+    qemuDomainObjPrivatePtr priv = NULL;
+
+    if (!(addrs = virDomainUSBAddressSetCreate()))
+        goto cleanup;
+
+    if (virDomainUSBAddressSetAddControllers(addrs, def) < 0)
+        goto cleanup;
+
+    if (virDomainUSBDeviceDefForeach(def, virDomainUSBAddressReserve, addrs,
+                                     true) < 0)
+        goto cleanup;
+
+    VIR_DEBUG("Existing USB addresses have been reserved");
+
+    if (obj && obj->privateData) {
+        priv = obj->privateData;
+        priv->usbaddrs = addrs;
+        addrs = NULL;
+    }
+    ret = 0;
+
+ cleanup:
+    virDomainUSBAddressSetFree(addrs);
+    return ret;
+}
+
+
 int
 qemuDomainAssignAddresses(virDomainDefPtr def,
                           virQEMUCapsPtr qemuCaps,
                           virDomainObjPtr obj,
-                          bool newDomain ATTRIBUTE_UNUSED)
+                          bool newDomain)
 {
     if (qemuDomainAssignVirtioSerialAddresses(def, obj) < 0)
         return -1;
@@ -1642,6 +1675,9 @@ qemuDomainAssignAddresses(virDomainDefPtr def,
     if (qemuDomainAssignPCIAddresses(def, qemuCaps, obj) < 0)
         return -1;
 
+    if (newDomain && qemuDomainAssignUSBAddresses(def, obj) < 0)
+        return -1;
+
     return 0;
 }
 
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-hub-conflict.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-hub-conflict.xml
new file mode 100644 (file)
index 0000000..9a48ba0
--- /dev/null
@@ -0,0 +1,22 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'/>
+    <memballoon model='virtio'/>
+    <hub type='usb'>
+      <address type='usb' bus='0' port='1'/>
+    </hub>
+    <input type='mouse' bus='usb'>
+      <address type='usb' bus='0' port='1'/>
+    </input>
+  </devices>
+</domain>
index afa3536a051ba025e4e29939699bc5efe4a7e5e4..e4a0bb30045fad3aa547ed8844ce1475fe1a5090 100644 (file)
@@ -1180,6 +1180,9 @@ mymain(void)
     DO_TEST("usb-hub",
             QEMU_CAPS_CHARDEV, QEMU_CAPS_USB_HUB,
             QEMU_CAPS_NODEFCONFIG);
+    DO_TEST_PARSE_ERROR("usb-hub-conflict",
+            QEMU_CAPS_CHARDEV, QEMU_CAPS_USB_HUB,
+            QEMU_CAPS_NODEFCONFIG);
     DO_TEST("usb-port-missing",
             QEMU_CAPS_CHARDEV, QEMU_CAPS_USB_HUB,
             QEMU_CAPS_NODEFCONFIG);