From 7888472ef1d57d992995a16dc7c9ba0fe18562a8 Mon Sep 17 00:00:00 2001 Message-Id: <7888472ef1d57d992995a16dc7c9ba0fe18562a8@dist-git> From: Yi Min Zhao Date: Mon, 8 Apr 2019 10:57:22 +0200 Subject: [PATCH] conf: Introduce address caching for PCI extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Boris Fiuczynski Reviewed-by: Bjoern Walk Reviewed-by: Ján Tomko Reviewed-by: Andrea Bolognani (cherry picked from commit 28831e1f1ec001882e907f03f7618f7c00ebc98d) https://bugzilla.redhat.com/show_bug.cgi?id=1508149 Conflicts: * src/conf/domain_addr.h + context - missing b72183223f3b Signed-off-by: Andrea Bolognani Message-Id: <20190408085732.28684-6-abologna@redhat.com> Reviewed-by: Laine Stump Reviewed-by: Ján Tomko --- src/bhyve/bhyve_device.c | 3 +- src/conf/domain_addr.c | 93 +++++++++++++++++++++++++++++++++- src/conf/domain_addr.h | 10 +++- src/qemu/qemu_domain_address.c | 6 ++- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c index 03aa6c93bd..8f0862b0b6 100644 --- a/src/bhyve/bhyve_device.c +++ b/src/bhyve/bhyve_device.c @@ -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], diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 39f22b82eb..3e33549c3d 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -27,6 +27,7 @@ #include "virlog.h" #include "virstring.h" #include "domain_addr.h" +#include "virhashcode.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -741,8 +742,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; @@ -753,6 +839,10 @@ virDomainPCIAddressSetAlloc(unsigned int nbuses) goto error; addrs->nbuses = nbuses; + + if (virDomainPCIAddressSetExtensionAlloc(addrs, extFlags) < 0) + goto error; + return addrs; error: @@ -767,6 +857,7 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs) if (!addrs) return; + virDomainPCIAddressSetExtensionFree(addrs); VIR_FREE(addrs->buses); VIR_FREE(addrs); } diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index fd06008e26..b01e6b9d20 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -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,6 +131,7 @@ 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; @@ -132,7 +139,8 @@ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr; char *virDomainPCIAddressAsString(virPCIDeviceAddressPtr addr) ATTRIBUTE_NONNULL(1); -virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses); +virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses, + virPCIDeviceAddressExtensionFlags extFlags); void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs); diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 3d01d14b46..ba870d56b1 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1508,8 +1508,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; -- 2.22.0