[libvirt] [PATCH 3/4] numatune: Set NUMA policy between fork and exec as a hook

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


* src/qemu/qemu_process.c (New function qemuProcessInitNumaPolicy,
  and invoke it in function qemuProcessHook)
---
 src/qemu/qemu_process.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index bd7c932..43d793c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -28,6 +28,10 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 
+#if HAVE_NUMACTL
+# include <numa.h>
+#endif
+
 #include "qemu_process.h"
 #include "qemu_domain.h"
 #include "qemu_cgroup.h"
@@ -1081,6 +1085,97 @@ qemuProcessDetectVcpuPIDs(struct qemud_driver *driver,
 }
 
 /*
+ * Set Numa policy for qemu process, to be run between fork/exec of
+ * QEMU only.
+ */
+#if HAVA_NUMACTL
+static int
+qemuProcessInitNumaPolicy(virDomainObjPtr vm)
+{
+    struct bitmask mask = NULL;
+    virErrorPtr orig_err = NULL;
+    virErrorPtr err = NULL;
+    int model = -1;
+    int node = -1;
+    int ret = -1;
+    int i = 0;
+
+    if (!vm->def->numatune.memory.nodeset)
+        return 0;
+
+    model = vm->def->numatune.memory.model;
+    mask = numa_parse_nodestring(vm->def->numatune.memory.nodeset);
+
+    orig_err = virSaveLastError();
+
+    if (model == VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
+        numa_set_bind_policy(1);
+        numa_set_membind(mask);
+        numa_set_bind_policy(0);
+
+        err = virGetLastError();
+        if ((err && (err->code != orig_err->code)) ||
+            (err && !orig_err)) {
+            VIR_ERROR(_("Failed to bind memory to nodeset '%s': %s"),
+                      vm->def->numatune.memory.nodeset,
+                      err ? err->message : _("unknown error"));
+            virResetLastError(err);
+            goto cleanup;
+        }
+    } else if (model == VIR_DOMAIN_NUMATUNE_MEM_PREFERRED) {
+        for (i=0; i<mask->size; i++) {
+            if (numa_bitmask_isbitset(mask, i))
+                node = i;
+        }
+
+        numa_set_bind_policy(0);
+        numa_set_preferred(node);
+
+        err = virGetLastError();
+        if ((err && (err->code != orig_err->code)) ||
+            (err && !orig_err)) {
+            VIR_ERROR(_("Failed to set memory policy as preferred to node "
+                      "'%s': %s"), vm->def->numatune.memory.nodeset,
+                      err ? err->message : _("unknown error"));
+            virResetLastError(err);
+            goto cleanup;
+        }
+    } else if (model == VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) {
+        numa_set_interleave_mask(mask);
+
+        err = virGetLastError();
+        if ((err && (err->code != orig_err->code)) ||
+            (err && !orig_err)) {
+            VIR_ERROR(_("Failed to interleave memory to nodeset '%s': %s"),
+                      vm->def->numatune.memory.nodeset,
+                      err ? err->message : _("unknown error"));
+            virResetLastError(err);
+            goto cleanup;
+        }
+    } else {
+        /* XXX: Shouldn't go here, as we already do checking when
+         * parsing domain XML.
+         */
+        qemuReportError(VIR_ERR_XML_ERROR,
+                        "%s", _("Invalid model for memory NUMA tuning."));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    numa_bitmask_free(mask);
+    return ret;
+}
+#else
+static int
+qemuProcessInitNumaPolicy(virDomainObjPtr vm ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+#endif
+
+/*
  * To be run between fork/exec of QEMU only
  */
 static int
@@ -1789,6 +1884,9 @@ static int qemuProcessHook(void *data)
     if (qemuProcessInitCpuAffinity(h->vm) < 0)
         return -1;
 
+    if (qemuProcessInitNumaPolicy(h->vm) < 0)
+        return -1;
+
     if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm) < 0)
         return -1;
 
-- 
1.7.4




More information about the libvir-list mailing list