From: Peter Krempa Date: Thu, 18 Jul 2013 09:21:48 +0000 (+0200) Subject: caps: Add helpers to convert NUMA nodes to corresponding CPUs X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=b8b38321e724b5b1b7858c415566ab5e6e96ec8c;p=libvirt.git caps: Add helpers to convert NUMA nodes to corresponding CPUs These helpers use the remembered host capabilities to retrieve the cpu map rather than query the host again. The intended usage for this helpers is to fix automatic NUMA placement with strict memory alloc. The code doing the prepare needs to pin the emulator process only to cpus belonging to a subset of NUMA nodes of the host. --- diff --git a/po/POTFILES.in b/po/POTFILES.in index 2e4ebc8011..1fd84af58a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -8,6 +8,7 @@ gnulib/lib/gai_strerror.c gnulib/lib/regcomp.c src/access/viraccessdriverpolkit.c src/access/viraccessmanager.c +src/conf/capabilities.c src/conf/cpu_conf.c src/conf/device_conf.c src/conf/domain_conf.c diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index bb5fe4ec60..1acc9366f7 100644 --- a/src/conf/capabilities.c +++ b/src/conf/capabilities.c @@ -916,3 +916,67 @@ virCapabilitiesFormatXML(virCapsPtr caps) return virBufferContentAndReset(&xml); } + +/* get the maximum ID of cpus in the host */ +static unsigned int +virCapabilitiesGetHostMaxcpu(virCapsPtr caps) +{ + unsigned int maxcpu = 0; + size_t node; + size_t cpu; + + for (node = 0; node < caps->host.nnumaCell; node++) { + virCapsHostNUMACellPtr cell = caps->host.numaCell[node]; + + for (cpu = 0; cpu < cell->ncpus; cpu++) { + if (cell->cpus[cpu].id > maxcpu) + maxcpu = cell->cpus[cpu].id; + } + } + + return maxcpu; +} + +/* set cpus of a numa node in the bitmask */ +static int +virCapabilitiesGetCpusForNode(virCapsPtr caps, + size_t node, + virBitmapPtr cpumask) +{ + virCapsHostNUMACellPtr cell = caps->host.numaCell[node]; + size_t cpu; + + for (cpu = 0; cpu < cell->ncpus; cpu++) { + if (virBitmapSetBit(cpumask, cell->cpus[cpu].id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cpu '%u' in node '%zu' is out of range " + "of the provided bitmap"), + cell->cpus[cpu].id, node); + return -1; + } + } + + return 0; +} + +virBitmapPtr +virCapabilitiesGetCpusForNodemask(virCapsPtr caps, + virBitmapPtr nodemask) +{ + virBitmapPtr ret = NULL; + unsigned int maxcpu = virCapabilitiesGetHostMaxcpu(caps); + ssize_t node = -1; + + if (!(ret = virBitmapNew(maxcpu + 1))) + return NULL; + + + while ((node = virBitmapNextSetBit(nodemask, node)) >= 0) { + if (virCapabilitiesGetCpusForNode(caps, node, ret) < 0) { + virBitmapFree(ret); + return NULL; + } + } + + return ret; +} diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index 6c7efdefdb..88ec4547f7 100644 --- a/src/conf/capabilities.h +++ b/src/conf/capabilities.h @@ -257,5 +257,7 @@ virCapabilitiesDefaultGuestEmulator(virCapsPtr caps, extern char * virCapabilitiesFormatXML(virCapsPtr caps); +virBitmapPtr virCapabilitiesGetCpusForNodemask(virCapsPtr caps, + virBitmapPtr nodemask); #endif /* __VIR_CAPABILITIES_H */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7a968fb0ec..ba9db26fd3 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -57,6 +57,7 @@ virCapabilitiesDefaultGuestMachine; virCapabilitiesFormatXML; virCapabilitiesFreeMachines; virCapabilitiesFreeNUMAInfo; +virCapabilitiesGetCpusForNodemask; virCapabilitiesNew; virCapabilitiesSetHostCPU;