render / rpms / libvirt

Forked from rpms/libvirt 4 months ago
Clone
e8e641
From 45a585374500f4e4f1684c9dafe89269344c79b1 Mon Sep 17 00:00:00 2001
e8e641
Message-Id: <45a585374500f4e4f1684c9dafe89269344c79b1@dist-git>
e8e641
From: Michal Privoznik <mprivozn@redhat.com>
e8e641
Date: Tue, 7 Mar 2023 14:05:54 +0100
e8e641
Subject: [PATCH] qemuBuildThreadContextProps: Prune .node-affinity wrt
e8e641
 <emulatorpin/>
e8e641
e8e641
When a thread-context object is specified on the cmd line, then
e8e641
QEMU spawns a thread and sets its affinity to the list of NUMA
e8e641
nodes specified in .node-affinity attribute. And this works just
e8e641
fine, until the main QEMU thread itself is not restricted.
e8e641
e8e641
Because of v5.3.0-rc1~18 we restrict the main emulator thread
e8e641
even before QEMU is executed and thus then it tries to set
e8e641
affinity of a thread-context thread, it inevitably fails with:
e8e641
e8e641
  Setting CPU affinity failed: Invalid argument
e8e641
e8e641
Now, we could lift the pinning temporarily, let QEMU spawn all
e8e641
thread-context threads, and enforce pinning again, but that would
e8e641
require some form of communication with QEMU (maybe -preconfig?).
e8e641
But that would still be wrong, because it would circumvent
e8e641
<emulatorpin/>.
e8e641
e8e641
Technically speaking, thread-context is an internal
e8e641
implementation detail of QEMU, and if it weren't for it, the main
e8e641
emulator thread would be doing the allocation. Therefore, we
e8e641
should honor the pinning and prune the list of node so that
e8e641
inaccessible ones are dropped.
e8e641
e8e641
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2154750
e8e641
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
e8e641
Reviewed-by: Kristina Hanicova <khanicov@redhat.com>
e8e641
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
e8e641
(cherry picked from commit df2ef2e706ec5960761bdbf619ea33be99482a15)
e8e641
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2185039
e8e641
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
e8e641
---
e8e641
 src/qemu/qemu_command.c                       | 25 ++++++++++++++++---
e8e641
 src/qemu/qemu_command.h                       |  1 +
e8e641
 ...emory-hotplug-dimm-addr.x86_64-latest.args |  2 +-
e8e641
 3 files changed, 24 insertions(+), 4 deletions(-)
e8e641
e8e641
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
e8e641
index 346967f51c..b36005d248 100644
e8e641
--- a/src/qemu/qemu_command.c
e8e641
+++ b/src/qemu/qemu_command.c
e8e641
@@ -3533,7 +3533,7 @@ qemuBuildMemoryDimmBackendStr(virCommand *cmd,
e8e641
                                     def, mem, true, false, &nodemask) < 0)
e8e641
         return -1;
e8e641
 
e8e641
-    if (qemuBuildThreadContextProps(&tcProps, &props, priv, nodemask) < 0)
e8e641
+    if (qemuBuildThreadContextProps(&tcProps, &props, def, priv, nodemask) < 0)
e8e641
         return -1;
e8e641
 
e8e641
     if (tcProps &&
e8e641
@@ -3630,10 +3630,13 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,
e8e641
 int
e8e641
 qemuBuildThreadContextProps(virJSONValue **tcProps,
e8e641
                             virJSONValue **memProps,
e8e641
+                            const virDomainDef *def,
e8e641
                             qemuDomainObjPrivate *priv,
e8e641
                             virBitmap *nodemask)
e8e641
 {
e8e641
     g_autoptr(virJSONValue) props = NULL;
e8e641
+    virBitmap *emulatorpin = NULL;
e8e641
+    g_autoptr(virBitmap) emulatorNodes = NULL;
e8e641
     g_autofree char *tcAlias = NULL;
e8e641
     const char *memalias = NULL;
e8e641
     bool prealloc = false;
e8e641
@@ -3650,6 +3653,22 @@ qemuBuildThreadContextProps(virJSONValue **tcProps,
e8e641
         !prealloc)
e8e641
         return 0;
e8e641
 
e8e641
+    emulatorpin = qemuDomainEvaluateCPUMask(def,
e8e641
+                                            def->cputune.emulatorpin,
e8e641
+                                            priv->autoNodeset);
e8e641
+
e8e641
+    if (emulatorpin && virNumaIsAvailable()) {
e8e641
+        if (virNumaCPUSetToNodeset(emulatorpin, &emulatorNodes) < 0)
e8e641
+            return -1;
e8e641
+
e8e641
+        virBitmapIntersect(emulatorNodes, nodemask);
e8e641
+
e8e641
+        if (virBitmapIsAllClear(emulatorNodes))
e8e641
+            return 0;
e8e641
+
e8e641
+        nodemask = emulatorNodes;
e8e641
+    }
e8e641
+
e8e641
     memalias = virJSONValueObjectGetString(*memProps, "id");
e8e641
     if (!memalias) {
e8e641
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
e8e641
@@ -7064,7 +7083,7 @@ qemuBuildMemCommandLineMemoryDefaultBackend(virCommand *cmd,
e8e641
                                     def, &mem, false, true, &nodemask) < 0)
e8e641
         return -1;
e8e641
 
e8e641
-    if (qemuBuildThreadContextProps(&tcProps, &props, priv, nodemask) < 0)
e8e641
+    if (qemuBuildThreadContextProps(&tcProps, &props, def, priv, nodemask) < 0)
e8e641
         return -1;
e8e641
 
e8e641
     if (tcProps &&
e8e641
@@ -7393,7 +7412,7 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg,
e8e641
             g_autoptr(virJSONValue) tcProps = NULL;
e8e641
 
e8e641
             if (qemuBuildThreadContextProps(&tcProps, &nodeBackends[i],
e8e641
-                                            priv, nodemask[i]) < 0)
e8e641
+                                            def, priv, nodemask[i]) < 0)
e8e641
                 goto cleanup;
e8e641
 
e8e641
             if (tcProps &&
e8e641
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
e8e641
index 17f326d13b..5fdb138030 100644
e8e641
--- a/src/qemu/qemu_command.h
e8e641
+++ b/src/qemu/qemu_command.h
e8e641
@@ -153,6 +153,7 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,
e8e641
 int
e8e641
 qemuBuildThreadContextProps(virJSONValue **tcProps,
e8e641
                             virJSONValue **memProps,
e8e641
+                            const virDomainDef *def,
e8e641
                             qemuDomainObjPrivate *priv,
e8e641
                             virBitmap *nodemask);
e8e641
 
e8e641
diff --git a/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args b/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args
e8e641
index 4e9bbde448..bbfb0f9a9e 100644
e8e641
--- a/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args
e8e641
+++ b/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args
e8e641
@@ -29,7 +29,7 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
e8e641
 -no-acpi \
e8e641
 -boot strict=on \
e8e641
 -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
e8e641
--object '{"qom-type":"thread-context","id":"tc-memdimm0","node-affinity":[1,2,3]}' \
e8e641
+-object '{"qom-type":"thread-context","id":"tc-memdimm0","node-affinity":[1,2]}' \
e8e641
 -object '{"qom-type":"memory-backend-file","id":"memdimm0","mem-path":"/dev/hugepages2M/libvirt/qemu/-1-QEMUGuest1","prealloc":true,"size":536870912,"host-nodes":[1,2,3],"policy":"bind","prealloc-context":"tc-memdimm0"}' \
e8e641
 -device '{"driver":"pc-dimm","node":0,"memdev":"memdimm0","id":"dimm0","slot":0,"addr":4294967296}' \
e8e641
 -object '{"qom-type":"memory-backend-ram","id":"memdimm2","size":536870912}' \
e8e641
-- 
e8e641
2.40.0