<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Mar 14, 2023 at 5:53 PM Michal Privoznik <<a href="mailto:mprivozn@redhat.com">mprivozn@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">When a thread-context object is specified on the cmd line, then<br>
QEMU spawns a thread and sets its affinity to the list of NUMA<br>
nodes specified in .node-affinity attribute. And this works just<br>
fine, until the main QEMU thread itself is not restricted.<br>
<br>
Because of v5.3.0-rc1~18 we restrict the main emulator thread<br>
even before QEMU is executed and thus then it tries to set<br>
affinity of a thread-context thread, it inevitably fails with:<br>
<br>
  Setting CPU affinity failed: Invalid argument<br>
<br>
Now, we could lift the pinning temporarily, let QEMU spawn all<br>
thread-context threads, and enforce pinning again, but that would<br>
require some form of communication with QEMU (maybe -preconfig?).<br>
But that would still be wrong, because it would circumvent<br>
<emulatorpin/>.<br>
<br>
Technically speaking, thread-context is an internal<br>
implementation detail of QEMU, and if it weren't for it, the main<br>
emulator thread would be doing the allocation. Therefore, we<br>
should honor the pinning and prune the list of node so that<br>
inaccessible ones are dropped.<br>
<br>
Resolves: <a href="https://bugzilla.redhat.com/show_bug.cgi?id=2154750" rel="noreferrer" target="_blank">https://bugzilla.redhat.com/show_bug.cgi?id=2154750</a><br>
Signed-off-by: Michal Privoznik <<a href="mailto:mprivozn@redhat.com" target="_blank">mprivozn@redhat.com</a>><br>
Reviewed-by: Andrea Bolognani <<a href="mailto:abologna@redhat.com" target="_blank">abologna@redhat.com</a>><br>
---<br>
 src/qemu/qemu_command.c                       | 26 ++++++++++++++++---<br>
 src/qemu/qemu_command.h                       |  1 +<br>
 ...emory-hotplug-dimm-addr.x86_64-latest.args |  2 +-<br>
 3 files changed, 25 insertions(+), 4 deletions(-)<br>
<br>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c<br>
index 6de3b549a0..7137edac8f 100644<br>
--- a/src/qemu/qemu_command.c<br>
+++ b/src/qemu/qemu_command.c<br>
@@ -3539,7 +3539,7 @@ qemuBuildMemoryDimmBackendStr(virCommand *cmd,<br>
                                     def, mem, true, false, &nodemask) < 0)<br>
         return -1;<br>
<br>
-    if (qemuBuildThreadContextProps(&tcProps, &props, priv, nodemask) < 0)<br>
+    if (qemuBuildThreadContextProps(&tcProps, &props, def, priv, nodemask) < 0)<br>
         return -1;<br>
<br>
     if (tcProps &&<br>
@@ -3636,10 +3636,13 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,<br>
 int<br>
 qemuBuildThreadContextProps(virJSONValue **tcProps,<br>
                             virJSONValue **memProps,<br>
+                            const virDomainDef *def,<br>
                             qemuDomainObjPrivate *priv,<br>
                             virBitmap *nodemask)<br>
 {<br>
     g_autoptr(virJSONValue) props = NULL;<br>
+    virBitmap *emulatorpin = NULL;<br>
+    g_autoptr(virBitmap) emulatorNodes = NULL;<br>
     g_autofree char *tcAlias = NULL;<br>
     const char *memalias = NULL;<br>
     bool prealloc = false;<br>
@@ -3656,6 +3659,23 @@ qemuBuildThreadContextProps(virJSONValue **tcProps,<br>
         !prealloc)<br>
         return 0;<br>
<br>
+    emulatorpin = qemuDomainEvaluateCPUMask(def,<br>
+                                            def->cputune.emulatorpin,<br>
+                                            priv->autoNodeset);<br>
+<br>
+    if (emulatorpin &&<br>
+        virNumaIsAvailable()) {<br></blockquote><div><br></div><div>Could have been on the same line.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+        if (virNumaCPUSetToNodeset(emulatorpin, &emulatorNodes) < 0)<br>
+            return -1;<br>
+<br>
+        virBitmapIntersect(emulatorNodes, nodemask);<br>
+<br>
+        if (virBitmapIsAllClear(emulatorNodes))<br>
+            return 0;<br>
+<br>
+        nodemask = emulatorNodes;<br>
+    }<br>
+<br>
     memalias = virJSONValueObjectGetString(*memProps, "id");<br>
     if (!memalias) {<br>
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
@@ -7188,7 +7208,7 @@ qemuBuildMemCommandLineMemoryDefaultBackend(virCommand *cmd,<br>
                                     def, &mem, false, true, &nodemask) < 0)<br>
         return -1;<br>
<br>
-    if (qemuBuildThreadContextProps(&tcProps, &props, priv, nodemask) < 0)<br>
+    if (qemuBuildThreadContextProps(&tcProps, &props, def, priv, nodemask) < 0)<br>
         return -1;<br>
<br>
     if (tcProps &&<br>
@@ -7517,7 +7537,7 @@ qemuBuildNumaCommandLine(virQEMUDriverConfig *cfg,<br>
             g_autoptr(virJSONValue) tcProps = NULL;<br>
<br>
             if (qemuBuildThreadContextProps(&tcProps, &nodeBackends[i],<br>
-                                            priv, nodemask[i]) < 0)<br>
+                                            def, priv, nodemask[i]) < 0)<br>
                 goto cleanup;<br>
<br>
             if (tcProps &&<br>
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h<br>
index 17f326d13b..5fdb138030 100644<br>
--- a/src/qemu/qemu_command.h<br>
+++ b/src/qemu/qemu_command.h<br>
@@ -153,6 +153,7 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,<br>
 int<br>
 qemuBuildThreadContextProps(virJSONValue **tcProps,<br>
                             virJSONValue **memProps,<br>
+                            const virDomainDef *def,<br>
                             qemuDomainObjPrivate *priv,<br>
                             virBitmap *nodemask);<br>
<br>
diff --git a/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args b/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args<br>
index 84360843fb..6ae1fd1b98 100644<br>
--- a/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args<br>
+++ b/tests/qemuxml2argvdata/memory-hotplug-dimm-addr.x86_64-latest.args<br>
@@ -28,7 +28,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \<br>
 -no-shutdown \<br>
 -boot strict=on \<br>
 -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \<br>
--object '{"qom-type":"thread-context","id":"tc-memdimm0","node-affinity":[1,2,3]}' \<br>
+-object '{"qom-type":"thread-context","id":"tc-memdimm0","node-affinity":[1,2]}' \<br>
 -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"}' \<br>
 -device '{"driver":"pc-dimm","node":0,"memdev":"memdimm0","id":"dimm0","slot":0,"addr":4294967296}' \<br>
 -object '{"qom-type":"memory-backend-ram","id":"memdimm2","size":536870912}' \<br>
-- <br>
2.39.2<br>
<br></blockquote><div><br></div><div><br></div><div><div>Reviewed-by: Kristina Hanicova <<a href="mailto:khanicov@redhat.com" target="_blank">khanicov@redhat.com</a>> <br></div><font style="--darkreader-inline-color: #b2a696;" color="#888888"><font style="--darkreader-inline-color: #b2a696;" color="#888888"><div><br></div><div>Kristina</div></font></font> <br></div></div></div>