]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: Introduce address caching for PCI extensions
authorYi Min Zhao <zyimin@linux.ibm.com>
Thu, 8 Nov 2018 11:00:24 +0000 (19:00 +0800)
committerAndrea Bolognani <abologna@redhat.com>
Thu, 15 Nov 2018 11:32:18 +0000 (12:32 +0100)
This patch provides a caching mechanism for the device address
extensions uid and fid on S390. For efficient sparse address allocation,
we introduce two hash tables for uid/fid which hold the address set
information per domain. Also in order to improve performance of
searching available value, we introduce our own callbacks for the two
hashtables. In this way, uid/fid is saved in hash key and hash value
could be any non-NULL pointer due to no operation on hash value. That is
also the reason why we don't introduce hash value free callback.

Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
src/bhyve/bhyve_device.c
src/conf/domain_addr.c
src/conf/domain_addr.h
src/qemu/qemu_domain_address.c

index 207ac6a2dd56a490b4c590b8ab1ef84c2f06d3da..a59dfe45195ff80f5f1e63055432196f90b1590d 100644 (file)
@@ -71,7 +71,8 @@ bhyveDomainPCIAddressSetCreate(virDomainDefPtr def, unsigned int nbuses)
 {
     virDomainPCIAddressSetPtr addrs;
 
-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
+    if ((addrs = virDomainPCIAddressSetAlloc(nbuses,
+                                             VIR_PCI_ADDRESS_EXTENSION_NONE)) == NULL)
         return NULL;
 
     if (virDomainPCIAddressBusSetModel(&addrs->buses[0],
index e4ed143b76b49c21a7ffeac417f8016075889363..0c00302c13854dc1d588e68de5fa8a49f75f57bb 100644 (file)
@@ -27,6 +27,7 @@
 #include "virlog.h"
 #include "virstring.h"
 #include "domain_addr.h"
+#include "virhashcode.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
 
@@ -727,8 +728,93 @@ virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
     addrs->buses[addr->bus].slot[addr->slot].functions &= ~(1 << addr->function);
 }
 
+
+static uint32_t
+virZPCIAddrKeyCode(const void *name,
+                   uint32_t seed)
+{
+    unsigned int value = *((unsigned int *)name);
+    return virHashCodeGen(&value, sizeof(value), seed);
+}
+
+
+static bool
+virZPCIAddrKeyEqual(const void *namea,
+                    const void *nameb)
+{
+    return *((unsigned int *)namea) == *((unsigned int *)nameb);
+}
+
+
+static void *
+virZPCIAddrKeyCopy(const void *name)
+{
+    unsigned int *copy;
+
+    if (VIR_ALLOC(copy) < 0)
+        return NULL;
+
+    *copy = *((unsigned int *)name);
+    return (void *)copy;
+}
+
+
+static void
+virZPCIAddrKeyFree(void *name)
+{
+    VIR_FREE(name);
+}
+
+
+static void
+virDomainPCIAddressSetExtensionFree(virDomainPCIAddressSetPtr addrs)
+{
+    if (!addrs || !addrs->zpciIds)
+        return;
+
+    virHashFree(addrs->zpciIds->uids);
+    virHashFree(addrs->zpciIds->fids);
+    VIR_FREE(addrs->zpciIds);
+}
+
+
+static int
+virDomainPCIAddressSetExtensionAlloc(virDomainPCIAddressSetPtr addrs,
+                                     virPCIDeviceAddressExtensionFlags extFlags)
+{
+    if (extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
+        if (addrs->zpciIds)
+            return 0;
+
+        if (VIR_ALLOC(addrs->zpciIds) < 0)
+            return -1;
+
+        if (!(addrs->zpciIds->uids = virHashCreateFull(10, NULL,
+                                                       virZPCIAddrKeyCode,
+                                                       virZPCIAddrKeyEqual,
+                                                       virZPCIAddrKeyCopy,
+                                                       virZPCIAddrKeyFree)))
+            goto error;
+
+        if (!(addrs->zpciIds->fids = virHashCreateFull(10, NULL,
+                                                       virZPCIAddrKeyCode,
+                                                       virZPCIAddrKeyEqual,
+                                                       virZPCIAddrKeyCopy,
+                                                       virZPCIAddrKeyFree)))
+            goto error;
+    }
+
+    return 0;
+
+ error:
+    virDomainPCIAddressSetExtensionFree(addrs);
+    return -1;
+}
+
+
 virDomainPCIAddressSetPtr
-virDomainPCIAddressSetAlloc(unsigned int nbuses)
+virDomainPCIAddressSetAlloc(unsigned int nbuses,
+                            virPCIDeviceAddressExtensionFlags extFlags)
 {
     virDomainPCIAddressSetPtr addrs;
 
@@ -739,6 +825,10 @@ virDomainPCIAddressSetAlloc(unsigned int nbuses)
         goto error;
 
     addrs->nbuses = nbuses;
+
+    if (virDomainPCIAddressSetExtensionAlloc(addrs, extFlags) < 0)
+        goto error;
+
     return addrs;
 
  error:
@@ -753,6 +843,7 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
     if (!addrs)
         return;
 
+    virDomainPCIAddressSetExtensionFree(addrs);
     VIR_FREE(addrs->buses);
     VIR_FREE(addrs);
 }
index 435b3c5d7f0d61ea4886880d1eb1b14f1870b20c..8d64d6b79505408d6a07516c160558cf5fb45a03 100644 (file)
@@ -116,6 +116,12 @@ typedef struct {
 } virDomainPCIAddressBus;
 typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
 
+typedef struct {
+    virHashTablePtr uids;
+    virHashTablePtr fids;
+} virDomainZPCIAddressIds;
+typedef virDomainZPCIAddressIds *virDomainZPCIAddressIdsPtr;
+
 struct _virDomainPCIAddressSet {
     virDomainPCIAddressBus *buses;
     size_t nbuses;
@@ -125,11 +131,13 @@ struct _virDomainPCIAddressSet {
     bool areMultipleRootsSupported;
     /* If true, the guest can use the pcie-to-pci-bridge controller */
     bool isPCIeToPCIBridgeSupported;
+    virDomainZPCIAddressIdsPtr zpciIds;
 };
 typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet;
 typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
 
-virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses);
+virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses,
+                                                      virPCIDeviceAddressExtensionFlags extFlags);
 
 void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
 
index 43bde31e81221cfabb6ea807bd7fb7464dc24de9..ae3e8f0845d9160787457a17f23c2e5acabb362a 100644 (file)
@@ -1510,8 +1510,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
     size_t i;
     bool hasPCIeRoot = false;
     virDomainControllerModelPCI defaultModel;
+    virPCIDeviceAddressExtensionFlags extFlags = VIR_PCI_ADDRESS_EXTENSION_NONE;
 
-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI))
+        extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
+
+    if ((addrs = virDomainPCIAddressSetAlloc(nbuses, extFlags)) == NULL)
         return NULL;
 
     addrs->dryRun = dryRun;