]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu_command: Introduce qemuBuildThreadContextProps()
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 2 Nov 2022 11:08:52 +0000 (12:08 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 15 Nov 2022 10:47:08 +0000 (11:47 +0100)
The aim of thread-context object is to set affinity on threads
that allocate memory for a memory-backend-* object. For instance:

-object '{"qom-type":"thread-context","id":"tc-ram-node0","node-affinity":[3]}' \
-object '{"qom-type":"memory-backend-memfd","id":"ram-node0","hugetlb":true,\
          "hugetlbsize":2097152,"share":true,"prealloc":true,"prealloc-threads":8,\
          "size":15032385536,"host-nodes":[3],"policy":"preferred",\
          "prealloc-context":"tc-ram-node0"}' \

allocates 14GiB worth of memory, backed by 2MiB hugepages from
host NUMA node 3, using 8 threads. If it weren't for
thread-context these threads wouldn't have any affinity and thus
theoretically could be scheduled to run on CPUs of different NUMA
node (which is what I saw occasionally).

Therefore, whenever we are pinning memory (IOW setting host-nodes
attribute), we can generate thread-context object with the same
affinity.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
src/qemu/qemu_command.c
src/qemu/qemu_command.h

index 41b9f7cb52237a217100b8bde3deff7cf0784b53..cf098523d082bb928b3c419355f93d426d25e474 100644 (file)
@@ -3603,6 +3603,53 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,
 }
 
 
+int
+qemuBuildThreadContextProps(virJSONValue **tcProps,
+                            virJSONValue **memProps,
+                            qemuDomainObjPrivate *priv)
+{
+    g_autoptr(virJSONValue) props = NULL;
+    virJSONValue *nodemask = NULL;
+    g_autoptr(virJSONValue) nodemaskCopy = NULL;
+    g_autofree char *tcAlias = NULL;
+    const char *memalias = NULL;
+
+    *tcProps = NULL;
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_THREAD_CONTEXT))
+        return 0;
+
+    nodemask = virJSONValueObjectGetArray(*memProps, "host-nodes");
+    if (!nodemask)
+        return 0;
+
+    memalias = virJSONValueObjectGetString(*memProps, "id");
+    if (!memalias) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("memory device alias is not assigned"));
+        return -1;
+    }
+
+    tcAlias = g_strdup_printf("tc-%s", memalias);
+    nodemaskCopy = virJSONValueCopy(nodemask);
+
+    if (virJSONValueObjectAdd(&props,
+                              "s:qom-type", "thread-context",
+                              "s:id", tcAlias,
+                              "a:node-affinity", &nodemaskCopy,
+                              NULL) < 0)
+        return -1;
+
+    if (virJSONValueObjectAdd(memProps,
+                              "s:prealloc-context", tcAlias,
+                              NULL) < 0)
+        return -1;
+
+    *tcProps = g_steal_pointer(&props);
+    return 0;
+}
+
+
 static char *
 qemuBuildLegacyNicStr(virDomainNetDef *net)
 {
index 2578367df93a75f174465017316c22a06cde49f1..761cc5d8650d544891d10929d7015e99739bf877 100644 (file)
@@ -147,6 +147,11 @@ qemuBuildMemoryDeviceProps(virQEMUDriverConfig *cfg,
                            const virDomainDef *def,
                            const virDomainMemoryDef *mem);
 
+int
+qemuBuildThreadContextProps(virJSONValue **tcProps,
+                            virJSONValue **memProps,
+                            qemuDomainObjPrivate *priv);
+
 /* Current, best practice */
 virJSONValue *
 qemuBuildPCIHostdevDevProps(const virDomainDef *def,