USB disks, redirected devices, host devices and serial devices
are supported.
---
src/conf/domain_addr.c | 34 +++++++++++++++++++
src/conf/domain_addr.h | 4 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 5 +++
src/qemu/qemu_hotplug.c | 39 ++++++++++++++++++++++
.../qemuhotplug-hotplug-base+disk-usb.xml | 1 +
6 files changed, 84 insertions(+)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 15f4753..42c0837 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -1522,3 +1522,37 @@ virDomainUSBAddressReserve(virDomainDefPtr def ATTRIBUTE_UNUSED,
VIR_FREE(portstr);
return ret;
}
+
+
+int
+virDomainUSBAddressRelease(virDomainUSBAddressSetPtr addrs,
+ virDomainDeviceInfoPtr info)
+{
+ virDomainUSBAddressHubPtr *port = NULL;
+ char *portstr = NULL;
+ int ret = -1;
+
+ if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB)
+ return 0;
+
+ portstr = virDomainUSBAddressGetPortString(info->addr.usb.port);
+ VIR_DEBUG("Releasing USB addr bus=%u port=%s", info->addr.usb.bus,
portstr);
+
+ if (virDomainUSBAddressFindPort(&port, addrs, info) < 0)
+ goto cleanup;
+
+ if (!*port) {
+ if ((*port)->nports) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("usb-hub hotunplug is not yet implemented"));
+ goto cleanup;
+ }
+ VIR_FREE(*port);
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(portstr);
+ return ret;
+}
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 8ecf588..fbd9557 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -281,4 +281,8 @@ virDomainUSBAddressReserve(virDomainDefPtr def,
virDomainDeviceInfoPtr info,
void *data)
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
+int
+virDomainUSBAddressRelease(virDomainUSBAddressSetPtr addrs,
+ virDomainDeviceInfoPtr info)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
#endif /* __DOMAIN_ADDR_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 048ec68..9c53b13 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -109,6 +109,7 @@ virDomainPCIAddressValidate;
virDomainUSBAddressAssign;
virDomainUSBAddressGetPortBuf;
virDomainUSBAddressGetPortString;
+virDomainUSBAddressRelease;
virDomainUSBAddressReserve;
virDomainUSBAddressSetAddControllers;
virDomainUSBAddressSetCreate;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9df542e..277e431 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2106,6 +2106,11 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
virDomainVirtioSerialAddrRelease(priv->vioserialaddrs, info) < 0)
VIR_WARN("Unable to release virtio-serial address on %s",
NULLSTR(devstr));
+ if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB &&
+ priv->usbaddrs &&
+ virDomainUSBAddressRelease(priv->usbaddrs, info) < 0)
+ VIR_WARN("Unable to release usb address on %s",
+ NULLSTR(devstr));
}
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 8e38153..e72237a 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -669,6 +669,7 @@ qemuDomainAttachUSBMassStorageDevice(virConnectPtr conn,
char *devstr = NULL;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
const char *src = virDomainDiskGetSource(disk);
+ bool releaseaddr;
for (i = 0; i < vm->def->ndisks; i++) {
if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
@@ -678,6 +679,16 @@ qemuDomainAttachUSBMassStorageDevice(virConnectPtr conn,
}
}
+ if (priv->usbaddrs) {
+ if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
+ if (virDomainUSBAddressReserve(NULL, NULL, &disk->info,
priv->usbaddrs) < 0)
+ goto cleanup;
+ } else if (virDomainUSBAddressAssign(priv->usbaddrs, &disk->info,
false) < 0) {
+ goto cleanup;
+ }
+ releaseaddr = true;
+ }
+
if (qemuDomainPrepareDisk(driver, vm, disk, NULL, false) < 0)
goto cleanup;
@@ -728,6 +739,8 @@ qemuDomainAttachUSBMassStorageDevice(virConnectPtr conn,
virDomainDiskInsertPreAlloced(vm->def, disk);
cleanup:
+ if (ret < 0 && releaseaddr)
+ virDomainUSBAddressRelease(priv->usbaddrs, &disk->info);
VIR_FREE(devstr);
VIR_FREE(drivestr);
virObjectUnref(cfg);
@@ -1536,6 +1549,16 @@ qemuDomainAttachChrDeviceAssignAddr(qemuDomainObjPrivatePtr priv,
return -1;
return 1;
+ } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
+ chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB) {
+ if (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
+ if (virDomainUSBAddressReserve(NULL, NULL, &chr->info,
priv->usbaddrs) < 0)
+ return -1;
+ } else if (virDomainUSBAddressAssign(priv->usbaddrs, &chr->info, false)
< 0) {
+ return -1;
+ }
+ return 1;
+
} else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
if (virDomainVirtioSerialAddrAutoAssign(NULL, priv->vioserialaddrs,
@@ -1845,11 +1868,22 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
{
qemuDomainObjPrivatePtr priv = vm->privateData;
char *devstr = NULL;
+ bool releaseaddr = false;
bool added = false;
bool teardowncgroup = false;
bool teardownlabel = false;
int ret = -1;
+ if (priv->usbaddrs) {
+ if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
+ if (virDomainUSBAddressReserve(NULL, NULL, hostdev->info,
priv->usbaddrs) < 0)
+ return -1;
+ } else if (virDomainUSBAddressAssign(priv->usbaddrs, hostdev->info, false)
< 0) {
+ goto cleanup;
+ }
+ releaseaddr = true;
+ }
+
if (qemuPrepareHostUSBDevices(driver, vm->def->name, &hostdev, 1, 0) <
0)
goto cleanup;
@@ -1902,6 +1936,8 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
VIR_WARN("Unable to restore host device labelling on hotplug
fail");
if (added)
qemuDomainReAttachHostUSBDevices(driver, vm->def->name, &hostdev,
1);
+ if (releaseaddr)
+ virDomainUSBAddressRelease(priv->usbaddrs, hostdev->info);
}
VIR_FREE(devstr);
return ret;
@@ -2856,6 +2892,8 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
dev.type = VIR_DOMAIN_DEVICE_DISK;
dev.data.disk = disk;
ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
+ if (priv->usbaddrs)
+ virDomainUSBAddressRelease(priv->usbaddrs, &disk->info);
virDomainDiskDefFree(disk);
return 0;
@@ -2949,6 +2987,7 @@ qemuDomainRemoveUSBHostDevice(virQEMUDriverPtr driver,
virDomainHostdevDefPtr hostdev)
{
qemuDomainReAttachHostUSBDevices(driver, vm->def->name, &hostdev, 1);
+ qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
}
static void
diff --git a/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base+disk-usb.xml
b/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base+disk-usb.xml
index 7904c4f..ac69490 100644
--- a/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base+disk-usb.xml
+++ b/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base+disk-usb.xml
@@ -25,6 +25,7 @@
<target dev='sdq' bus='usb'/>
<readonly/>
<shareable/>
+ <address type='usb' bus='0' port='1'/>
</disk>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x01' function='0x2'/>
--
2.4.6