[libvirt] [PATCH 9/9] Assign addresses on USB device hotplug

Ján Tomko jtomko at redhat.com
Wed Aug 12 14:52:19 UTC 2015


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




More information about the libvir-list mailing list