c313de
From 7888472ef1d57d992995a16dc7c9ba0fe18562a8 Mon Sep 17 00:00:00 2001
c313de
Message-Id: <7888472ef1d57d992995a16dc7c9ba0fe18562a8@dist-git>
c313de
From: Yi Min Zhao <zyimin@linux.ibm.com>
c313de
Date: Mon, 8 Apr 2019 10:57:22 +0200
c313de
Subject: [PATCH] conf: Introduce address caching for PCI extensions
c313de
MIME-Version: 1.0
c313de
Content-Type: text/plain; charset=UTF-8
c313de
Content-Transfer-Encoding: 8bit
c313de
c313de
This patch provides a caching mechanism for the device address
c313de
extensions uid and fid on S390. For efficient sparse address allocation,
c313de
we introduce two hash tables for uid/fid which hold the address set
c313de
information per domain. Also in order to improve performance of
c313de
searching available value, we introduce our own callbacks for the two
c313de
hashtables. In this way, uid/fid is saved in hash key and hash value
c313de
could be any non-NULL pointer due to no operation on hash value. That is
c313de
also the reason why we don't introduce hash value free callback.
c313de
c313de
Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
c313de
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
c313de
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
c313de
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c313de
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
c313de
c313de
(cherry picked from commit 28831e1f1ec001882e907f03f7618f7c00ebc98d)
c313de
c313de
https://bugzilla.redhat.com/show_bug.cgi?id=1508149
c313de
c313de
Conflicts:
c313de
c313de
  * src/conf/domain_addr.h
c313de
    + context
c313de
      - missing b72183223f3b
c313de
c313de
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
c313de
Message-Id: <20190408085732.28684-6-abologna@redhat.com>
c313de
Reviewed-by: Laine Stump <laine@redhat.com>
c313de
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c313de
---
c313de
 src/bhyve/bhyve_device.c       |  3 +-
c313de
 src/conf/domain_addr.c         | 93 +++++++++++++++++++++++++++++++++-
c313de
 src/conf/domain_addr.h         | 10 +++-
c313de
 src/qemu/qemu_domain_address.c |  6 ++-
c313de
 4 files changed, 108 insertions(+), 4 deletions(-)
c313de
c313de
diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c
c313de
index 03aa6c93bd..8f0862b0b6 100644
c313de
--- a/src/bhyve/bhyve_device.c
c313de
+++ b/src/bhyve/bhyve_device.c
c313de
@@ -71,7 +71,8 @@ bhyveDomainPCIAddressSetCreate(virDomainDefPtr def, unsigned int nbuses)
c313de
 {
c313de
     virDomainPCIAddressSetPtr addrs;
c313de
 
c313de
-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
c313de
+    if ((addrs = virDomainPCIAddressSetAlloc(nbuses,
c313de
+                                             VIR_PCI_ADDRESS_EXTENSION_NONE)) == NULL)
c313de
         return NULL;
c313de
 
c313de
     if (virDomainPCIAddressBusSetModel(&addrs->buses[0],
c313de
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
c313de
index 39f22b82eb..3e33549c3d 100644
c313de
--- a/src/conf/domain_addr.c
c313de
+++ b/src/conf/domain_addr.c
c313de
@@ -27,6 +27,7 @@
c313de
 #include "virlog.h"
c313de
 #include "virstring.h"
c313de
 #include "domain_addr.h"
c313de
+#include "virhashcode.h"
c313de
 
c313de
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
c313de
 
c313de
@@ -741,8 +742,93 @@ virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
c313de
     addrs->buses[addr->bus].slot[addr->slot].functions &= ~(1 << addr->function);
c313de
 }
c313de
 
c313de
+
c313de
+static uint32_t
c313de
+virZPCIAddrKeyCode(const void *name,
c313de
+                   uint32_t seed)
c313de
+{
c313de
+    unsigned int value = *((unsigned int *)name);
c313de
+    return virHashCodeGen(&value, sizeof(value), seed);
c313de
+}
c313de
+
c313de
+
c313de
+static bool
c313de
+virZPCIAddrKeyEqual(const void *namea,
c313de
+                    const void *nameb)
c313de
+{
c313de
+    return *((unsigned int *)namea) == *((unsigned int *)nameb);
c313de
+}
c313de
+
c313de
+
c313de
+static void *
c313de
+virZPCIAddrKeyCopy(const void *name)
c313de
+{
c313de
+    unsigned int *copy;
c313de
+
c313de
+    if (VIR_ALLOC(copy) < 0)
c313de
+        return NULL;
c313de
+
c313de
+    *copy = *((unsigned int *)name);
c313de
+    return (void *)copy;
c313de
+}
c313de
+
c313de
+
c313de
+static void
c313de
+virZPCIAddrKeyFree(void *name)
c313de
+{
c313de
+    VIR_FREE(name);
c313de
+}
c313de
+
c313de
+
c313de
+static void
c313de
+virDomainPCIAddressSetExtensionFree(virDomainPCIAddressSetPtr addrs)
c313de
+{
c313de
+    if (!addrs || !addrs->zpciIds)
c313de
+        return;
c313de
+
c313de
+    virHashFree(addrs->zpciIds->uids);
c313de
+    virHashFree(addrs->zpciIds->fids);
c313de
+    VIR_FREE(addrs->zpciIds);
c313de
+}
c313de
+
c313de
+
c313de
+static int
c313de
+virDomainPCIAddressSetExtensionAlloc(virDomainPCIAddressSetPtr addrs,
c313de
+                                     virPCIDeviceAddressExtensionFlags extFlags)
c313de
+{
c313de
+    if (extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
c313de
+        if (addrs->zpciIds)
c313de
+            return 0;
c313de
+
c313de
+        if (VIR_ALLOC(addrs->zpciIds) < 0)
c313de
+            return -1;
c313de
+
c313de
+        if (!(addrs->zpciIds->uids = virHashCreateFull(10, NULL,
c313de
+                                                       virZPCIAddrKeyCode,
c313de
+                                                       virZPCIAddrKeyEqual,
c313de
+                                                       virZPCIAddrKeyCopy,
c313de
+                                                       virZPCIAddrKeyFree)))
c313de
+            goto error;
c313de
+
c313de
+        if (!(addrs->zpciIds->fids = virHashCreateFull(10, NULL,
c313de
+                                                       virZPCIAddrKeyCode,
c313de
+                                                       virZPCIAddrKeyEqual,
c313de
+                                                       virZPCIAddrKeyCopy,
c313de
+                                                       virZPCIAddrKeyFree)))
c313de
+            goto error;
c313de
+    }
c313de
+
c313de
+    return 0;
c313de
+
c313de
+ error:
c313de
+    virDomainPCIAddressSetExtensionFree(addrs);
c313de
+    return -1;
c313de
+}
c313de
+
c313de
+
c313de
 virDomainPCIAddressSetPtr
c313de
-virDomainPCIAddressSetAlloc(unsigned int nbuses)
c313de
+virDomainPCIAddressSetAlloc(unsigned int nbuses,
c313de
+                            virPCIDeviceAddressExtensionFlags extFlags)
c313de
 {
c313de
     virDomainPCIAddressSetPtr addrs;
c313de
 
c313de
@@ -753,6 +839,10 @@ virDomainPCIAddressSetAlloc(unsigned int nbuses)
c313de
         goto error;
c313de
 
c313de
     addrs->nbuses = nbuses;
c313de
+
c313de
+    if (virDomainPCIAddressSetExtensionAlloc(addrs, extFlags) < 0)
c313de
+        goto error;
c313de
+
c313de
     return addrs;
c313de
 
c313de
  error:
c313de
@@ -767,6 +857,7 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
c313de
     if (!addrs)
c313de
         return;
c313de
 
c313de
+    virDomainPCIAddressSetExtensionFree(addrs);
c313de
     VIR_FREE(addrs->buses);
c313de
     VIR_FREE(addrs);
c313de
 }
c313de
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
c313de
index fd06008e26..b01e6b9d20 100644
c313de
--- a/src/conf/domain_addr.h
c313de
+++ b/src/conf/domain_addr.h
c313de
@@ -116,6 +116,12 @@ typedef struct {
c313de
 } virDomainPCIAddressBus;
c313de
 typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
c313de
 
c313de
+typedef struct {
c313de
+    virHashTablePtr uids;
c313de
+    virHashTablePtr fids;
c313de
+} virDomainZPCIAddressIds;
c313de
+typedef virDomainZPCIAddressIds *virDomainZPCIAddressIdsPtr;
c313de
+
c313de
 struct _virDomainPCIAddressSet {
c313de
     virDomainPCIAddressBus *buses;
c313de
     size_t nbuses;
c313de
@@ -125,6 +131,7 @@ struct _virDomainPCIAddressSet {
c313de
     bool areMultipleRootsSupported;
c313de
     /* If true, the guest can use the pcie-to-pci-bridge controller */
c313de
     bool isPCIeToPCIBridgeSupported;
c313de
+    virDomainZPCIAddressIdsPtr zpciIds;
c313de
 };
c313de
 typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet;
c313de
 typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
c313de
@@ -132,7 +139,8 @@ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
c313de
 char *virDomainPCIAddressAsString(virPCIDeviceAddressPtr addr)
c313de
       ATTRIBUTE_NONNULL(1);
c313de
 
c313de
-virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses);
c313de
+virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses,
c313de
+                                                      virPCIDeviceAddressExtensionFlags extFlags);
c313de
 
c313de
 void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
c313de
 
c313de
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
c313de
index 3d01d14b46..ba870d56b1 100644
c313de
--- a/src/qemu/qemu_domain_address.c
c313de
+++ b/src/qemu/qemu_domain_address.c
c313de
@@ -1508,8 +1508,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
c313de
     size_t i;
c313de
     bool hasPCIeRoot = false;
c313de
     virDomainControllerModelPCI defaultModel;
c313de
+    virPCIDeviceAddressExtensionFlags extFlags = VIR_PCI_ADDRESS_EXTENSION_NONE;
c313de
 
c313de
-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
c313de
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI))
c313de
+        extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
c313de
+
c313de
+    if ((addrs = virDomainPCIAddressSetAlloc(nbuses, extFlags)) == NULL)
c313de
         return NULL;
c313de
 
c313de
     addrs->dryRun = dryRun;
c313de
-- 
c313de
2.22.0
c313de