6ae9ed
From 758b25f47af79cd6da43a4bc13599b0bb64afef1 Mon Sep 17 00:00:00 2001
6ae9ed
Message-Id: <758b25f47af79cd6da43a4bc13599b0bb64afef1@dist-git>
6ae9ed
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
6ae9ed
Date: Thu, 21 Jul 2016 15:57:56 +0200
6ae9ed
Subject: [PATCH] Assign addresses on USB device hotplug
6ae9ed
MIME-Version: 1.0
6ae9ed
Content-Type: text/plain; charset=UTF-8
6ae9ed
Content-Transfer-Encoding: 8bit
6ae9ed
6ae9ed
USB disks, redirected devices, host devices and serial devices
6ae9ed
are supported.
6ae9ed
6ae9ed
(cherry picked from commit f2a781ceb075073a6033b96649f41501148d3c0c)
6ae9ed
Signed-off-by: Ján Tomko <jtomko@redhat.com>
6ae9ed
6ae9ed
https://bugzilla.redhat.com/show_bug.cgi?id=1215968
6ae9ed
---
6ae9ed
 src/conf/domain_addr.c                             | 30 ++++++++++++++++++++++
6ae9ed
 src/conf/domain_addr.h                             |  5 ++++
6ae9ed
 src/libvirt_private.syms                           |  1 +
6ae9ed
 src/qemu/qemu_domain_address.c                     |  5 ++++
6ae9ed
 src/qemu/qemu_hotplug.c                            | 27 +++++++++++++++++++
6ae9ed
 .../qemuhotplug-hotplug-base-live+disk-usb.xml     |  1 +
6ae9ed
 6 files changed, 69 insertions(+)
6ae9ed
6ae9ed
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
6ae9ed
index 3b0c205..365ee40 100644
6ae9ed
--- a/src/conf/domain_addr.c
6ae9ed
+++ b/src/conf/domain_addr.c
6ae9ed
@@ -1735,3 +1735,33 @@ virDomainUSBAddressEnsure(virDomainUSBAddressSetPtr addrs,
6ae9ed
 
6ae9ed
     return 0;
6ae9ed
 }
6ae9ed
+
6ae9ed
+
6ae9ed
+int
6ae9ed
+virDomainUSBAddressRelease(virDomainUSBAddressSetPtr addrs,
6ae9ed
+                           virDomainDeviceInfoPtr info)
6ae9ed
+{
6ae9ed
+    virDomainUSBAddressHubPtr targetHub = NULL;
6ae9ed
+    char *portStr = NULL;
6ae9ed
+    int targetPort;
6ae9ed
+    int ret = -1;
6ae9ed
+
6ae9ed
+    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB ||
6ae9ed
+        !virDomainUSBAddressPortIsValid(info->addr.usb.port))
6ae9ed
+        return 0;
6ae9ed
+
6ae9ed
+    portStr = virDomainUSBAddressPortFormat(info->addr.usb.port);
6ae9ed
+    VIR_DEBUG("Releasing USB addr bus=%u port=%s", info->addr.usb.bus, portStr);
6ae9ed
+
6ae9ed
+    if (!(targetHub = virDomainUSBAddressFindPort(addrs, info, &targetPort,
6ae9ed
+                                                  portStr)))
6ae9ed
+        goto cleanup;
6ae9ed
+
6ae9ed
+    ignore_value(virBitmapClearBit(targetHub->portmap, targetPort));
6ae9ed
+
6ae9ed
+    ret = 0;
6ae9ed
+
6ae9ed
+ cleanup:
6ae9ed
+    VIR_FREE(portStr);
6ae9ed
+    return ret;
6ae9ed
+}
6ae9ed
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
6ae9ed
index 633aa16..cc36aed 100644
6ae9ed
--- a/src/conf/domain_addr.h
6ae9ed
+++ b/src/conf/domain_addr.h
6ae9ed
@@ -293,4 +293,9 @@ int
6ae9ed
 virDomainUSBAddressEnsure(virDomainUSBAddressSetPtr addrs,
6ae9ed
                           virDomainDeviceInfoPtr info)
6ae9ed
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
6ae9ed
+
6ae9ed
+int
6ae9ed
+virDomainUSBAddressRelease(virDomainUSBAddressSetPtr addrs,
6ae9ed
+                           virDomainDeviceInfoPtr info)
6ae9ed
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
6ae9ed
 #endif /* __DOMAIN_ADDR_H__ */
6ae9ed
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
6ae9ed
index 4727d39..e23bfe3 100644
6ae9ed
--- a/src/libvirt_private.syms
6ae9ed
+++ b/src/libvirt_private.syms
6ae9ed
@@ -112,6 +112,7 @@ virDomainUSBAddressEnsure;
6ae9ed
 virDomainUSBAddressPortFormat;
6ae9ed
 virDomainUSBAddressPortFormatBuf;
6ae9ed
 virDomainUSBAddressPortIsValid;
6ae9ed
+virDomainUSBAddressRelease;
6ae9ed
 virDomainUSBAddressReserve;
6ae9ed
 virDomainUSBAddressSetAddControllers;
6ae9ed
 virDomainUSBAddressSetAddHub;
6ae9ed
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
6ae9ed
index 21c2ecf..7499026 100644
6ae9ed
--- a/src/qemu/qemu_domain_address.c
6ae9ed
+++ b/src/qemu/qemu_domain_address.c
6ae9ed
@@ -1772,4 +1772,9 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
6ae9ed
         virDomainVirtioSerialAddrRelease(priv->vioserialaddrs, info) < 0)
6ae9ed
         VIR_WARN("Unable to release virtio-serial address on %s",
6ae9ed
                  NULLSTR(devstr));
6ae9ed
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB &&
6ae9ed
+        priv->usbaddrs &&
6ae9ed
+        virDomainUSBAddressRelease(priv->usbaddrs, info) < 0)
6ae9ed
+        VIR_WARN("Unable to release USB address on %s",
6ae9ed
+                 NULLSTR(devstr));
6ae9ed
 }
6ae9ed
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
6ae9ed
index cba0e8c..36885a3 100644
6ae9ed
--- a/src/qemu/qemu_hotplug.c
6ae9ed
+++ b/src/qemu/qemu_hotplug.c
6ae9ed
@@ -640,6 +640,13 @@ qemuDomainAttachUSBMassStorageDevice(virQEMUDriverPtr driver,
6ae9ed
     char *devstr = NULL;
6ae9ed
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
6ae9ed
     const char *src = virDomainDiskGetSource(disk);
6ae9ed
+    bool releaseaddr = false;
6ae9ed
+
6ae9ed
+    if (priv->usbaddrs) {
6ae9ed
+        if (virDomainUSBAddressEnsure(priv->usbaddrs, &disk->info) < 0)
6ae9ed
+            goto cleanup;
6ae9ed
+        releaseaddr = true;
6ae9ed
+    }
6ae9ed
 
6ae9ed
     if (qemuDomainPrepareDisk(driver, vm, disk, NULL, false) < 0)
6ae9ed
         goto cleanup;
6ae9ed
@@ -685,6 +692,8 @@ qemuDomainAttachUSBMassStorageDevice(virQEMUDriverPtr driver,
6ae9ed
     virDomainDiskInsertPreAlloced(vm->def, disk);
6ae9ed
 
6ae9ed
  cleanup:
6ae9ed
+    if (ret < 0 && releaseaddr)
6ae9ed
+        virDomainUSBAddressRelease(priv->usbaddrs, &disk->info);
6ae9ed
     VIR_FREE(devstr);
6ae9ed
     VIR_FREE(drivestr);
6ae9ed
     virObjectUnref(cfg);
6ae9ed
@@ -1486,6 +1495,12 @@ qemuDomainAttachChrDeviceAssignAddr(qemuDomainObjPrivatePtr priv,
6ae9ed
             return -1;
6ae9ed
         return 1;
6ae9ed
 
6ae9ed
+    } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
6ae9ed
+               chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB) {
6ae9ed
+        if (virDomainUSBAddressEnsure(priv->usbaddrs, &chr->info) < 0)
6ae9ed
+            return -1;
6ae9ed
+        return 1;
6ae9ed
+
6ae9ed
     } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
6ae9ed
                chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
6ae9ed
         if (virDomainVirtioSerialAddrAutoAssign(NULL, priv->vioserialaddrs,
6ae9ed
@@ -1804,11 +1819,18 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
6ae9ed
 {
6ae9ed
     qemuDomainObjPrivatePtr priv = vm->privateData;
6ae9ed
     char *devstr = NULL;
6ae9ed
+    bool releaseaddr = false;
6ae9ed
     bool added = false;
6ae9ed
     bool teardowncgroup = false;
6ae9ed
     bool teardownlabel = false;
6ae9ed
     int ret = -1;
6ae9ed
 
6ae9ed
+    if (priv->usbaddrs) {
6ae9ed
+        if (virDomainUSBAddressEnsure(priv->usbaddrs, hostdev->info) < 0)
6ae9ed
+            goto cleanup;
6ae9ed
+        releaseaddr = true;
6ae9ed
+    }
6ae9ed
+
6ae9ed
     if (qemuHostdevPrepareUSBDevices(driver, vm->def->name, &hostdev, 1, 0) < 0)
6ae9ed
         goto cleanup;
6ae9ed
 
6ae9ed
@@ -1854,6 +1876,8 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
6ae9ed
             VIR_WARN("Unable to restore host device labelling on hotplug fail");
6ae9ed
         if (added)
6ae9ed
             qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1);
6ae9ed
+        if (releaseaddr)
6ae9ed
+            virDomainUSBAddressRelease(priv->usbaddrs, hostdev->info);
6ae9ed
     }
6ae9ed
     VIR_FREE(devstr);
6ae9ed
     return ret;
6ae9ed
@@ -2851,6 +2875,8 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
6ae9ed
     dev.type = VIR_DOMAIN_DEVICE_DISK;
6ae9ed
     dev.data.disk = disk;
6ae9ed
     ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
6ae9ed
+    if (priv->usbaddrs)
6ae9ed
+        virDomainUSBAddressRelease(priv->usbaddrs, &disk->info);
6ae9ed
 
6ae9ed
     virDomainDiskDefFree(disk);
6ae9ed
     return 0;
6ae9ed
@@ -2947,6 +2973,7 @@ qemuDomainRemoveUSBHostDevice(virQEMUDriverPtr driver,
6ae9ed
                               virDomainHostdevDefPtr hostdev)
6ae9ed
 {
6ae9ed
     qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1);
6ae9ed
+    qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
6ae9ed
 }
6ae9ed
 
6ae9ed
 static void
6ae9ed
diff --git a/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base-live+disk-usb.xml b/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base-live+disk-usb.xml
6ae9ed
index 41039a4..cd686e6 100644
6ae9ed
--- a/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base-live+disk-usb.xml
6ae9ed
+++ b/tests/qemuhotplugtestdata/qemuhotplug-hotplug-base-live+disk-usb.xml
6ae9ed
@@ -27,6 +27,7 @@
6ae9ed
       <readonly/>
6ae9ed
       <shareable/>
6ae9ed
       <alias name='usb-disk16'/>
6ae9ed
+      <address type='usb' bus='0' port='1'/>
6ae9ed
     </disk>
6ae9ed
     <controller type='usb' index='0'>
6ae9ed
       <alias name='usb'/>
6ae9ed
-- 
6ae9ed
2.9.2
6ae9ed