[PATCH 13/17] Reserve existing USB addresses

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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                             | 48 ++++++++++++++++++++++
 src/conf/domain_addr.h                             |  6 +++
 src/libvirt_private.syms                           |  1 +
 src/qemu/qemu_domain.h                             |  1 +
 src/qemu/qemu_domain_address.c                     | 37 ++++++++++++++++-
 .../qemuxml2argv-usb-hub-conflict.xml              | 22 ++++++++++
 tests/qemuxml2argvtest.c                           |  3 ++
 7 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-usb-hub-conflict.xml

diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 50d23b4..0706e6e 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -1495,6 +1495,14 @@ virDomainUSBAddressSetAddHub(virDomainUSBAddressSetPtr addrs,
     if (!(newHub = virDomainUSBAddressHubNew(VIR_DOMAIN_USB_HUB_PORTS)))
         goto cleanup;
 
+    /* TODO: remove in the next patch.
+     * Skip hubs with no address to pass 'make check' until we start
+     * auto-assigning their addresses */
+    if (hub->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+        ret = 0;
+        goto cleanup;
+    }
+
     if (hub->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
         virReportError(VIR_ERR_XML_ERROR, "%s",
                        _("Wrong address type for USB hub"));
@@ -1541,3 +1549,43 @@ int virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
     }
     return 0;
 }
+
+
+int
+virDomainUSBAddressReserve(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                           virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+                           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;
+
+    portstr = virDomainUSBAddressPortFormat(info->addr.usb.port);
+    if (!portstr)
+        goto cleanup;
+    VIR_DEBUG("Reserving USB addr bus=%u port=%s", info->addr.usb.bus, portstr);
+
+    if (!(targetHub = virDomainUSBAddressFindPort(addrs, info, &targetPort)))
+        goto cleanup;
+
+    if (virBitmapIsBitSet(targetHub->ports, targetPort)) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("Duplicate USB address %s"),
+                       portstr);
+        goto cleanup;
+    }
+
+    ignore_value(virBitmapSetBit(targetHub->ports, targetPort));
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(portstr);
+    return ret;
+}
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 693c5ee..502b1a2 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -271,4 +271,10 @@ int virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 void virDomainUSBAddressSetFree(virDomainUSBAddressSetPtr addrs);
 
+int
+virDomainUSBAddressReserve(virDomainDefPtr def,
+                           virDomainDeviceDefPtr dev,
+                           virDomainDeviceInfoPtr info,
+                           void *data)
+    ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
 #endif /* __DOMAIN_ADDR_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 63d1dd9..765ac0f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -111,6 +111,7 @@ virDomainPCIAddressValidate;
 virDomainPCIControllerModelToConnectType;
 virDomainUSBAddressPortFormat;
 virDomainUSBAddressPortFormatBuf;
+virDomainUSBAddressReserve;
 virDomainUSBAddressSetAddControllers;
 virDomainUSBAddressSetCreate;
 virDomainUSBAddressSetFree;
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 2443e97..e2141ed 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -190,6 +190,7 @@ struct _qemuDomainObjPrivate {
     virDomainPCIAddressSetPtr pciaddrs;
     virDomainCCWAddressSetPtr ccwaddrs;
     virDomainVirtioSerialAddrSetPtr vioserialaddrs;
+    virDomainUSBAddressSetPtr usbaddrs;
 
     virQEMUCapsPtr qemuCaps;
     char *lockState;
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 1382a53..c5f4150 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -1619,11 +1619,43 @@ 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 (virDomainDeviceInfoIterate(def, virDomainUSBAddressReserve, addrs) < 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;
@@ -1639,6 +1671,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
index 0000000..9a48ba0
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-hub-conflict.xml
@@ -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>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 2a8f6c4..1a01240 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1159,6 +1159,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-ports",
             QEMU_CAPS_CHARDEV, QEMU_CAPS_USB_HUB,
             QEMU_CAPS_NODEFCONFIG);
-- 
2.7.3

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]