render / rpms / libvirt

Forked from rpms/libvirt a year ago
Clone
c313de
From 87e3a5f2f797c79516a560ddc224074c834ef528 Mon Sep 17 00:00:00 2001
c313de
Message-Id: <87e3a5f2f797c79516a560ddc224074c834ef528@dist-git>
c313de
From: Yi Min Zhao <zyimin@linux.ibm.com>
c313de
Date: Mon, 8 Apr 2019 10:57:27 +0200
c313de
Subject: [PATCH] conf: Allocate/release 'uid' and 'fid' in PCI address
c313de
MIME-Version: 1.0
c313de
Content-Type: text/plain; charset=UTF-8
c313de
Content-Transfer-Encoding: 8bit
c313de
c313de
This patch adds new functions for reservation, assignment and release
c313de
to handle the uid/fid. If the uid/fid is defined in the domain XML,
c313de
they will be reserved directly in the collecting phase. If any of them
c313de
is not defined, we will find out an available value for them from the
c313de
zPCI address hashtable, and reserve them. For the hotplug case there
c313de
might not be a zPCI definition. So allocate and reserve uid/fid the
c313de
case. Assign if needed and reserve uid/fid for the defined case.
c313de
c313de
Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
c313de
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
c313de
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
c313de
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
c313de
c313de
(cherry picked from commit f183b87fc1dbcc6446ac3c1cef9cdd345b9725fb)
c313de
c313de
https://bugzilla.redhat.com/show_bug.cgi?id=1508149
c313de
c313de
Conflicts:
c313de
c313de
  * src/libvirt_private.syms
c313de
    + several symbols are not present in the list
c313de
      - missing 9ad119f4db5, ab3f781a10c, edeef779585, b899726faa5
c313de
c313de
  * src/qemu/qemu_domain_address.c
c313de
    + the old name for virDeviceInfoPCIAddressIsPresent() is used
c313de
      - missing 76151a53a100
c313de
c313de
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
c313de
Message-Id: <20190408085732.28684-11-abologna@redhat.com>
c313de
Reviewed-by: Laine Stump <laine@redhat.com>
c313de
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c313de
---
c313de
 src/conf/device_conf.c         |  16 +++
c313de
 src/conf/device_conf.h         |   3 +
c313de
 src/conf/domain_addr.c         | 244 +++++++++++++++++++++++++++++++++
c313de
 src/conf/domain_addr.h         |  12 ++
c313de
 src/libvirt_private.syms       |   5 +
c313de
 src/qemu/qemu_domain_address.c |  59 +++++++-
c313de
 6 files changed, 338 insertions(+), 1 deletion(-)
c313de
c313de
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
c313de
index cadac32603..76370d30a2 100644
c313de
--- a/src/conf/device_conf.c
c313de
+++ b/src/conf/device_conf.c
c313de
@@ -28,6 +28,7 @@
c313de
 #include "viruuid.h"
c313de
 #include "virbuffer.h"
c313de
 #include "device_conf.h"
c313de
+#include "domain_addr.h"
c313de
 #include "virstring.h"
c313de
 
c313de
 #define VIR_FROM_THIS VIR_FROM_DEVICE
c313de
@@ -230,6 +231,21 @@ int virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
c313de
 }
c313de
 
c313de
 
c313de
+bool
c313de
+virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info)
c313de
+{
c313de
+    return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
c313de
+           virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
c313de
+}
c313de
+
c313de
+bool
c313de
+virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info)
c313de
+{
c313de
+    return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
c313de
+           !virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
c313de
+}
c313de
+
c313de
+
c313de
 int
c313de
 virPCIDeviceAddressParseXML(xmlNodePtr node,
c313de
                             virPCIDeviceAddressPtr addr)
c313de
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
c313de
index c79066ec02..6bef2f093a 100644
c313de
--- a/src/conf/device_conf.h
c313de
+++ b/src/conf/device_conf.h
c313de
@@ -214,6 +214,9 @@ virDeviceInfoPCIAddressPresent(const virDomainDeviceInfo *info)
c313de
        !virPCIDeviceAddressIsEmpty(&info->addr.pci);
c313de
 }
c313de
 
c313de
+bool virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info);
c313de
+bool virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info);
c313de
+
c313de
 int virPCIDeviceAddressParseXML(xmlNodePtr node,
c313de
                                 virPCIDeviceAddressPtr addr);
c313de
 
c313de
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
c313de
index 9e0a0fdf95..a58910c394 100644
c313de
--- a/src/conf/domain_addr.c
c313de
+++ b/src/conf/domain_addr.c
c313de
@@ -33,6 +33,238 @@
c313de
 
c313de
 VIR_LOG_INIT("conf.domain_addr");
c313de
 
c313de
+static int
c313de
+virDomainZPCIAddressReserveId(virHashTablePtr set,
c313de
+                              unsigned int id,
c313de
+                              const char *name)
c313de
+{
c313de
+    if (virHashLookup(set, &id)) {
c313de
+        virReportError(VIR_ERR_INTERNAL_ERROR,
c313de
+                       _("zPCI %s %o is already reserved"),
c313de
+                       name, id);
c313de
+        return -1;
c313de
+    }
c313de
+
c313de
+    if (virHashAddEntry(set, &id, (void*)1) < 0) {
c313de
+        virReportError(VIR_ERR_INTERNAL_ERROR,
c313de
+                       _("Failed to reserve %s %o"),
c313de
+                       name, id);
c313de
+        return -1;
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressReserveUid(virHashTablePtr set,
c313de
+                               virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    return virDomainZPCIAddressReserveId(set, addr->uid, "uid");
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressReserveFid(virHashTablePtr set,
c313de
+                               virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    return virDomainZPCIAddressReserveId(set, addr->fid, "fid");
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressAssignId(virHashTablePtr set,
c313de
+                             unsigned int *id,
c313de
+                             unsigned int min,
c313de
+                             unsigned int max,
c313de
+                             const char *name)
c313de
+{
c313de
+    while (virHashLookup(set, &min)) {
c313de
+        if (min == max) {
c313de
+            virReportError(VIR_ERR_INTERNAL_ERROR,
c313de
+                           _("There is no more free %s."),
c313de
+                           name);
c313de
+            return -1;
c313de
+        }
c313de
+        ++min;
c313de
+    }
c313de
+    *id = min;
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressAssignUid(virHashTablePtr set,
c313de
+                              virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    return virDomainZPCIAddressAssignId(set, &addr->uid, 1,
c313de
+                                        VIR_DOMAIN_DEVICE_ZPCI_MAX_UID, "uid");
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressAssignFid(virHashTablePtr set,
c313de
+                              virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    return virDomainZPCIAddressAssignId(set, &addr->fid, 0,
c313de
+                                        VIR_DOMAIN_DEVICE_ZPCI_MAX_FID, "fid");
c313de
+}
c313de
+
c313de
+
c313de
+static void
c313de
+virDomainZPCIAddressReleaseId(virHashTablePtr set,
c313de
+                              unsigned int *id,
c313de
+                              const char *name)
c313de
+{
c313de
+    if (virHashRemoveEntry(set, id) < 0) {
c313de
+        virReportError(VIR_ERR_INTERNAL_ERROR,
c313de
+                       _("Release %s %o failed"),
c313de
+                       name, *id);
c313de
+    }
c313de
+
c313de
+    *id = 0;
c313de
+}
c313de
+
c313de
+
c313de
+static void
c313de
+virDomainZPCIAddressReleaseUid(virHashTablePtr set,
c313de
+                               virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    virDomainZPCIAddressReleaseId(set, &addr->uid, "uid");
c313de
+}
c313de
+
c313de
+
c313de
+static void
c313de
+virDomainZPCIAddressReleaseFid(virHashTablePtr set,
c313de
+                               virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    virDomainZPCIAddressReleaseId(set, &addr->fid, "fid");
c313de
+}
c313de
+
c313de
+
c313de
+static void
c313de
+virDomainZPCIAddressReleaseIds(virDomainZPCIAddressIdsPtr zpciIds,
c313de
+                               virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    if (!zpciIds || virZPCIDeviceAddressIsEmpty(addr))
c313de
+        return;
c313de
+
c313de
+    virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
c313de
+
c313de
+    virDomainZPCIAddressReleaseFid(zpciIds->fids, addr);
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressReserveNextUid(virHashTablePtr uids,
c313de
+                                   virZPCIDeviceAddressPtr zpci)
c313de
+{
c313de
+    if (virDomainZPCIAddressAssignUid(uids, zpci) < 0)
c313de
+        return -1;
c313de
+
c313de
+    if (virDomainZPCIAddressReserveUid(uids, zpci) < 0)
c313de
+        return -1;
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressReserveNextFid(virHashTablePtr fids,
c313de
+                                   virZPCIDeviceAddressPtr zpci)
c313de
+{
c313de
+    if (virDomainZPCIAddressAssignFid(fids, zpci) < 0)
c313de
+        return -1;
c313de
+
c313de
+    if (virDomainZPCIAddressReserveFid(fids, zpci) < 0)
c313de
+        return -1;
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressReserveAddr(virDomainZPCIAddressIdsPtr zpciIds,
c313de
+                                virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    if (virDomainZPCIAddressReserveUid(zpciIds->uids, addr) < 0)
c313de
+        return -1;
c313de
+
c313de
+    if (virDomainZPCIAddressReserveFid(zpciIds->fids, addr) < 0) {
c313de
+        virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
c313de
+        return -1;
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainZPCIAddressReserveNextAddr(virDomainZPCIAddressIdsPtr zpciIds,
c313de
+                                    virZPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    if (virDomainZPCIAddressReserveNextUid(zpciIds->uids, addr) < 0)
c313de
+        return -1;
c313de
+
c313de
+    if (virDomainZPCIAddressReserveNextFid(zpciIds->fids, addr) < 0) {
c313de
+        virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
c313de
+        return -1;
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+int
c313de
+virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
c313de
+                                        virPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
c313de
+        /* Reserve uid/fid to ZPCI device which has defined uid/fid
c313de
+         * in the domain.
c313de
+         */
c313de
+        return virDomainZPCIAddressReserveAddr(addrs->zpciIds, &addr->zpci);
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
+int
c313de
+virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
c313de
+                                            virPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
c313de
+        virZPCIDeviceAddress zpci = { 0 };
c313de
+
c313de
+        if (virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, &zpci) < 0)
c313de
+            return -1;
c313de
+
c313de
+        if (!addrs->dryRun)
c313de
+            addr->zpci = zpci;
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+static int
c313de
+virDomainPCIAddressExtensionEnsureAddr(virDomainPCIAddressSetPtr addrs,
c313de
+                                       virPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
c313de
+        virZPCIDeviceAddressPtr zpci = &addr->zpci;
c313de
+
c313de
+        if (virZPCIDeviceAddressIsEmpty(zpci))
c313de
+            return virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, zpci);
c313de
+        else
c313de
+            return virDomainZPCIAddressReserveAddr(addrs->zpciIds, zpci);
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
+
c313de
 virDomainPCIConnectFlags
c313de
 virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model)
c313de
 {
c313de
@@ -729,12 +961,24 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
c313de
         ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1);
c313de
     }
c313de
 
c313de
+    dev->addr.pci.extFlags = dev->pciAddrExtFlags;
c313de
+    ret = virDomainPCIAddressExtensionEnsureAddr(addrs, &dev->addr.pci);
c313de
+
c313de
  cleanup:
c313de
     VIR_FREE(addrStr);
c313de
     return ret;
c313de
 }
c313de
 
c313de
 
c313de
+void
c313de
+virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
c313de
+                                        virPCIDeviceAddressPtr addr)
c313de
+{
c313de
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
c313de
+        virDomainZPCIAddressReleaseIds(addrs->zpciIds, &addr->zpci);
c313de
+}
c313de
+
c313de
+
c313de
 void
c313de
 virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
c313de
                                virPCIDeviceAddressPtr addr)
c313de
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
c313de
index b01e6b9d20..e5ce4868d5 100644
c313de
--- a/src/conf/domain_addr.h
c313de
+++ b/src/conf/domain_addr.h
c313de
@@ -166,6 +166,14 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
c313de
                                   virPCIDeviceAddressPtr addr)
c313de
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
c313de
 
c313de
+int virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
c313de
+                                            virPCIDeviceAddressPtr addr)
c313de
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
c313de
+
c313de
+int virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
c313de
+                                                virPCIDeviceAddressPtr addr)
c313de
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
c313de
+
c313de
 int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
c313de
                                    virPCIDeviceAddressPtr addr,
c313de
                                    virDomainPCIConnectFlags flags,
c313de
@@ -187,6 +195,10 @@ void virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
c313de
                                     virPCIDeviceAddressPtr addr)
c313de
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
c313de
 
c313de
+void virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
c313de
+                                             virPCIDeviceAddressPtr addr)
c313de
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
c313de
+
c313de
 void virDomainPCIAddressSetAllMulti(virDomainDefPtr def)
c313de
     ATTRIBUTE_NONNULL(1);
c313de
 
c313de
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c313de
index b2a2a1f265..ee7625b0f3 100644
c313de
--- a/src/libvirt_private.syms
c313de
+++ b/src/libvirt_private.syms
c313de
@@ -93,6 +93,8 @@ virCPUModeTypeToString;
c313de
 
c313de
 
c313de
 # conf/device_conf.h
c313de
+virDeviceInfoPCIAddressExtensionIsPresent;
c313de
+virDeviceInfoPCIAddressExtensionIsWanted;
c313de
 virDomainDeviceInfoAddressIsEqual;
c313de
 virDomainDeviceInfoCopy;
c313de
 virInterfaceLinkFormat;
c313de
@@ -114,6 +116,9 @@ virDomainPCIAddressAsString;
c313de
 virDomainPCIAddressBusIsFullyReserved;
c313de
 virDomainPCIAddressBusSetModel;
c313de
 virDomainPCIAddressEnsureAddr;
c313de
+virDomainPCIAddressExtensionReleaseAddr;
c313de
+virDomainPCIAddressExtensionReserveAddr;
c313de
+virDomainPCIAddressExtensionReserveNextAddr;
c313de
 virDomainPCIAddressReleaseAddr;
c313de
 virDomainPCIAddressReserveAddr;
c313de
 virDomainPCIAddressReserveNextAddr;
c313de
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
c313de
index ba870d56b1..8338241cba 100644
c313de
--- a/src/qemu/qemu_domain_address.c
c313de
+++ b/src/qemu/qemu_domain_address.c
c313de
@@ -1405,6 +1405,24 @@ qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
c313de
 }
c313de
 
c313de
 
c313de
+static int
c313de
+qemuDomainAssignPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
c313de
+                                    virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
c313de
+                                    virDomainDeviceInfoPtr info,
c313de
+                                    void *opaque)
c313de
+{
c313de
+    virDomainPCIAddressSetPtr addrs = opaque;
c313de
+    virPCIDeviceAddressPtr addr = &info->addr.pci;
c313de
+
c313de
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
c313de
+        addr->extFlags = info->pciAddrExtFlags;
c313de
+
c313de
+    if (virDeviceInfoPCIAddressExtensionIsWanted(info))
c313de
+        return virDomainPCIAddressExtensionReserveNextAddr(addrs, addr);
c313de
+
c313de
+    return 0;
c313de
+}
c313de
+
c313de
 static int
c313de
 qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
c313de
                             virDomainDeviceDefPtr device,
c313de
@@ -1498,6 +1516,31 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
c313de
     return ret;
c313de
 }
c313de
 
c313de
+static int
c313de
+qemuDomainCollectPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
c313de
+                                     virDomainDeviceDefPtr device,
c313de
+                                     virDomainDeviceInfoPtr info,
c313de
+                                     void *opaque)
c313de
+{
c313de
+    virDomainPCIAddressSetPtr addrs = opaque;
c313de
+    virPCIDeviceAddressPtr addr = &info->addr.pci;
c313de
+
c313de
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
c313de
+        addr->extFlags = info->pciAddrExtFlags;
c313de
+
c313de
+    if (!virDeviceInfoPCIAddressExtensionIsPresent(info) ||
c313de
+        ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) &&
c313de
+         (device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) {
c313de
+        /* If a hostdev has a parent, its info will be a part of the
c313de
+         * parent, and will have its address collected during the scan
c313de
+         * of the parent's device type.
c313de
+        */
c313de
+        return 0;
c313de
+    }
c313de
+
c313de
+    return virDomainPCIAddressExtensionReserveAddr(addrs, addr);
c313de
+}
c313de
+
c313de
 static virDomainPCIAddressSetPtr
c313de
 qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
c313de
                               virQEMUCapsPtr qemuCaps,
c313de
@@ -1589,6 +1632,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
c313de
     if (virDomainDeviceInfoIterate(def, qemuDomainCollectPCIAddress, addrs) < 0)
c313de
         goto error;
c313de
 
c313de
+    if (virDomainDeviceInfoIterate(def,
c313de
+                                   qemuDomainCollectPCIAddressExtension,
c313de
+                                   addrs) < 0) {
c313de
+        goto error;
c313de
+    }
c313de
+
c313de
     return addrs;
c313de
 
c313de
  error:
c313de
@@ -2590,6 +2639,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
c313de
         if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
c313de
             goto cleanup;
c313de
 
c313de
+        if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
c313de
+            goto cleanup;
c313de
+
c313de
         /* Only for *new* domains with pcie-root (and no other
c313de
          * manually specified PCI controllers in the definition): If,
c313de
          * after assigning addresses/reserving slots for all devices,
c313de
@@ -2684,6 +2736,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
c313de
         if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
c313de
             goto cleanup;
c313de
 
c313de
+        if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
c313de
+            goto cleanup;
c313de
+
c313de
         /* set multi attribute for devices at function 0 of
c313de
          * any slot that has multiple functions in use
c313de
          */
c313de
@@ -3143,8 +3198,10 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
c313de
     if (!devstr)
c313de
         devstr = info->alias;
c313de
 
c313de
-    if (virDeviceInfoPCIAddressPresent(info))
c313de
+    if (virDeviceInfoPCIAddressPresent(info)) {
c313de
         virDomainPCIAddressReleaseAddr(priv->pciaddrs, &info->addr.pci);
c313de
+        virDomainPCIAddressExtensionReleaseAddr(priv->pciaddrs, &info->addr.pci);
c313de
+    }
c313de
 
c313de
     if (virDomainUSBAddressRelease(priv->usbaddrs, info) < 0)
c313de
         VIR_WARN("Unable to release USB address on %s", NULLSTR(devstr));
c313de
-- 
c313de
2.22.0
c313de