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