mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
Reserve existing USB addresses
Check if they fit on the USB controllers the domain has, and error out if two devices try to use the same address.
This commit is contained in:
parent
2f0813515e
commit
ddd31fd7dc
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -110,6 +110,7 @@ virDomainPCIControllerModelToConnectType;
|
||||
virDomainUSBAddressPortFormat;
|
||||
virDomainUSBAddressPortFormatBuf;
|
||||
virDomainUSBAddressPortIsValid;
|
||||
virDomainUSBAddressReserve;
|
||||
virDomainUSBAddressSetAddControllers;
|
||||
virDomainUSBAddressSetCreate;
|
||||
virDomainUSBAddressSetFree;
|
||||
|
@ -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);
|
||||
|
@ -187,6 +187,7 @@ struct _qemuDomainObjPrivate {
|
||||
virDomainPCIAddressSetPtr pciaddrs;
|
||||
virDomainCCWAddressSetPtr ccwaddrs;
|
||||
virDomainVirtioSerialAddrSetPtr vioserialaddrs;
|
||||
virDomainUSBAddressSetPtr usbaddrs;
|
||||
|
||||
virQEMUCapsPtr qemuCaps;
|
||||
char *lockState;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
22
tests/qemuxml2argvdata/qemuxml2argv-usb-hub-conflict.xml
Normal file
22
tests/qemuxml2argvdata/qemuxml2argv-usb-hub-conflict.xml
Normal file
@ -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>
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user