* 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