* 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