[libvirt] [PATCH 2/4] numatune: Support persistent XML for numa tuning

Osier Yang jyang at redhat.com
Thu May 12 10:22:51 UTC 2011


* 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




More information about the libvir-list mailing list