1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-26 03:21:44 +03:00

conf: Introduce address caching for PCI extensions

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>
This commit is contained in:
Yi Min Zhao 2018-11-08 19:00:24 +08:00 committed by Andrea Bolognani
parent 478e5f90fd
commit 28831e1f1e
4 changed files with 108 additions and 4 deletions

View 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],

View 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);
}

View 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);

View 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;