* src/conf/domain_conf.h (Define data stucture for new XML) * src/conf/domain_conf.c (Parse and Format new XML) * src/libvirt_private.syms (Add functions that to convert numa memory tuning model types to string, or inversely) --- src/conf/domain_conf.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 21 +++++++++++ src/libvirt_private.syms | 2 + 3 files changed, 114 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d3efec6..038c6ad 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -30,6 +30,10 @@ #include <dirent.h> #include <sys/time.h> +#if HAVE_NUMACTL +# include <numa.h> +#endif + #include "virterror_internal.h" #include "datatypes.h" #include "domain_conf.h" @@ -421,6 +425,11 @@ VIR_ENUM_IMPL(virDomainTimerMode, VIR_DOMAIN_TIMER_MODE_LAST, "paravirt", "smpsafe"); +VIR_ENUM_IMPL(virDomainNumatuneMemModel, VIR_DOMAIN_NUMATUNE_MEM_LAST, + "strict", + "preferred", + "interleave"); + #define virDomainReportError(code, ...) \ virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, __VA_ARGS__) @@ -1006,6 +1015,8 @@ void virDomainDefFree(virDomainDefPtr def) virDomainVcpupinDefFree(def->cputune.vcpupin, def->cputune.nvcpupin); + VIR_FREE(def->numatune.memory.nodeset); + virSysinfoDefFree(def->sysinfo); if (def->namespaceData && def->ns.free) @@ -5551,6 +5562,77 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } VIR_FREE(nodes); + /* Extract numatune if exists. */ + if ((n = virXPathNodeSet("./numatune", ctxt, NULL)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract numatune nodes")); + goto error; + } + + if (n) { +#ifdef HAVE_NUMACTL + if (numa_available() < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Host kernel is not aware of NUMA.")); + goto error; + } + + tmp = virXPathString("string(./numatune/memory/@model)", ctxt); + if (tmp) { + if ((def->numatune.memory.model = + virDomainNumatuneMemModelTypeFromString(tmp)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("Unsupported NUMA memory tuning model '%s'"), + tmp); + goto error; + } + VIR_FREE(tmp); + } else { + def->numatune.memory.model = VIR_DOMAIN_NUMATUNE_MEM_STRICT; + } + + char * nodeset = NULL; + nodeset = virXPathString("string(./numatune/memory/@nodeset)", ctxt); + if (!nodeset) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("nodeset for NUMA memory tuning must be set")); + goto error; + } + + struct bitmask *mask = NULL; + mask = numa_parse_nodestring(nodeset); + if (!mask) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid nodeset for NUMA memory tuning")); + goto error; + } + + int nnodes = 0; + if (def->numatune.memory.model == VIR_DOMAIN_NUMATUNE_MEM_PREFERRED) { + for (i=0; i<mask->size; i++) { + if (numa_bitmask_isbitset(mask, i)) { + nnodes++; + } + } + + if (nnodes != 1) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("NUMA memory tuning in 'preferred' mode " + "only supports single node")); + numa_bitmask_free(mask); + goto error; + } + } + + def->numatune.memory.nodeset = nodeset; + numa_bitmask_free(mask); +#else + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("libvirt is compiled without NUMA tuning support")); + goto error; +#endif + } + n = virXPathNodeSet("./features/*", ctxt, &nodes); if (n < 0) goto error; @@ -8219,6 +8301,15 @@ char *virDomainDefFormat(virDomainDefPtr def, if (def->cputune.shares || def->cputune.vcpupin) virBufferAddLit(&buf, " </cputune>\n"); + if (def->numatune.memory.nodeset) + virBufferAddLit(&buf, " <numatune>\n"); + if (def->numatune.memory.nodeset) + virBufferAsprintf(&buf, " <memory model='%s' nodeset='%s'/>\n", + virDomainNumatuneMemModelTypeToString(def->numatune.memory.model), + def->numatune.memory.nodeset); + if (def->numatune.memory.nodeset) + virBufferAddLit(&buf, " </numatune>\n"); + if (def->sysinfo) virDomainSysinfoDefFormat(&buf, def->sysinfo); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a0f820c..8685611 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1085,6 +1085,24 @@ int virDomainVcpupinIsDuplicate(virDomainVcpupinDefPtr *def, virDomainVcpupinDefPtr virDomainVcpupinFindByVcpu(virDomainVcpupinDefPtr *def, int nvcpupin, int vcpu); +enum virDomainNumatuneMemModel { + VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE, + VIR_DOMAIN_NUMATUNE_MEM_STRICT, + VIR_DOMAIN_NUMATUNE_MEM_PREFERRED, + + VIR_DOMAIN_NUMATUNE_MEM_LAST +}; + +typedef struct _virDomainNumatuneDef virDomainNumatuneDef; +typedef virDomainNumatuneDef *virDomainNumatuneDefPtr; +struct _virDomainNumatuneDef { + struct { + char *nodeset; + int model; + } memory; + + /* Future NUMA tuning related stuff should go here. */ +}; /* Guest VM main configuration */ typedef struct _virDomainDef virDomainDef; @@ -1120,6 +1138,8 @@ struct _virDomainDef { virDomainVcpupinDefPtr *vcpupin; } cputune; + virDomainNumatuneDef numatune; + /* These 3 are based on virDomainLifeCycleAction enum flags */ int onReboot; int onPoweroff; @@ -1492,6 +1512,7 @@ VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression) VIR_ENUM_DECL(virDomainGraphicsSpiceJpegCompression) VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression) VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression) +VIR_ENUM_DECL(virDomainNumatuneMemModel) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainSeclabel) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e2e706d..0ca4f8a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -289,6 +289,8 @@ virDomainMemballoonModelTypeFromString; virDomainMemballoonModelTypeToString; virDomainNetDefFree; virDomainNetTypeToString; +virDomainNumatuneMemModelTypeFromString; +virDomainNumatuneMemModelTypeToString; virDomainObjAssignDef; virDomainObjCopyPersistentDef; virDomainObjGetPersistentDef; -- 1.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list