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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list