4aa5c4
From 19f7e6dc950baf346738f462ac5c6b815c04edcc Mon Sep 17 00:00:00 2001
4aa5c4
Message-Id: <19f7e6dc950baf346738f462ac5c6b815c04edcc@dist-git>
4aa5c4
From: Michal Privoznik <mprivozn@redhat.com>
4aa5c4
Date: Mon, 21 Mar 2022 16:49:25 +0100
4aa5c4
Subject: [PATCH] conf: Introduce memory allocation threads
4aa5c4
4aa5c4
Since its v5.0.0 release QEMU is capable of specifying number of
4aa5c4
threads used to allocate memory. It defaults to 1, which may be
4aa5c4
too low for humongous guests with gigantic pages.
4aa5c4
4aa5c4
In general, on QEMU cmd line level it is possible to use
4aa5c4
different number of threads per each memory-backend-* object, in
4aa5c4
practical terms it's not useful. Therefore, use <memoryBacking/>
4aa5c4
to set guest wide value and let all memory devices 'inherit' it,
4aa5c4
silently. IOW, don't introduce per device knob because that would
4aa5c4
only complicate things for a little or no benefit.
4aa5c4
4aa5c4
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
4aa5c4
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
4aa5c4
(cherry picked from commit ba7f98126fa84d354ce72929b77cc111a9a557a9)
4aa5c4
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2067126
4aa5c4
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
4aa5c4
---
4aa5c4
 docs/formatdomain.rst                        |  8 +++++---
4aa5c4
 docs/schemas/domaincommon.rng                | 19 +++++++++++++------
4aa5c4
 src/conf/domain_conf.c                       | 15 ++++++++++++++-
4aa5c4
 src/conf/domain_conf.h                       |  1 +
4aa5c4
 tests/qemuxml2argvdata/memfd-memory-numa.xml |  2 +-
4aa5c4
 5 files changed, 34 insertions(+), 11 deletions(-)
4aa5c4
4aa5c4
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
4aa5c4
index 8128e43da4..17e89a0c0d 100644
4aa5c4
--- a/docs/formatdomain.rst
4aa5c4
+++ b/docs/formatdomain.rst
4aa5c4
@@ -977,7 +977,7 @@ Memory Backing
4aa5c4
        <locked/>
4aa5c4
        <source type="file|anonymous|memfd"/>
4aa5c4
        <access mode="shared|private"/>
4aa5c4
-       <allocation mode="immediate|ondemand"/>
4aa5c4
+       <allocation mode="immediate|ondemand" threads='8'/>
4aa5c4
        <discard/>
4aa5c4
      </memoryBacking>
4aa5c4
      ...
4aa5c4
@@ -1026,8 +1026,10 @@ influence how virtual memory pages are backed by host pages.
4aa5c4
    Using the ``mode`` attribute, specify if the memory is to be "shared" or
4aa5c4
    "private". This can be overridden per numa node by ``memAccess``.
4aa5c4
 ``allocation``
4aa5c4
-   Using the ``mode`` attribute, specify when to allocate the memory by
4aa5c4
-   supplying either "immediate" or "ondemand".
4aa5c4
+   Using the optional ``mode`` attribute, specify when to allocate the memory by
4aa5c4
+   supplying either "immediate" or "ondemand". :since:`Since 8.2.0` it is
4aa5c4
+   possible to set the number of threads that hypervisor uses to allocate
4aa5c4
+   memory via ``threads`` attribute.
4aa5c4
 ``discard``
4aa5c4
    When set and supported by hypervisor the memory content is discarded just
4aa5c4
    before guest shuts down (or when DIMM module is unplugged). Please note that
4aa5c4
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
4aa5c4
index 7fa5c2b8b5..c9c1529979 100644
4aa5c4
--- a/docs/schemas/domaincommon.rng
4aa5c4
+++ b/docs/schemas/domaincommon.rng
4aa5c4
@@ -745,12 +745,19 @@
4aa5c4
             </optional>
4aa5c4
             <optional>
4aa5c4
               <element name="allocation">
4aa5c4
-                <attribute name="mode">
4aa5c4
-                  <choice>
4aa5c4
-                    <value>immediate</value>
4aa5c4
-                    <value>ondemand</value>
4aa5c4
-                  </choice>
4aa5c4
-                </attribute>
4aa5c4
+                <optional>
4aa5c4
+                  <attribute name="mode">
4aa5c4
+                    <choice>
4aa5c4
+                      <value>immediate</value>
4aa5c4
+                      <value>ondemand</value>
4aa5c4
+                    </choice>
4aa5c4
+                  </attribute>
4aa5c4
+                </optional>
4aa5c4
+                <optional>
4aa5c4
+                  <attribute name="threads">
4aa5c4
+                    <ref name="unsignedInt"/>
4aa5c4
+                  </attribute>
4aa5c4
+                </optional>
4aa5c4
               </element>
4aa5c4
             </optional>
4aa5c4
             <optional>
4aa5c4
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
4aa5c4
index 5691b8d2d5..805a15848e 100644
4aa5c4
--- a/src/conf/domain_conf.c
4aa5c4
+++ b/src/conf/domain_conf.c
4aa5c4
@@ -19095,6 +19095,13 @@ virDomainDefParseMemory(virDomainDef *def,
4aa5c4
         VIR_FREE(tmp);
4aa5c4
     }
4aa5c4
 
4aa5c4
+    if (virXPathUInt("string(./memoryBacking/allocation/@threads)",
4aa5c4
+                     ctxt, &def->mem.allocation_threads) == -2) {
4aa5c4
+        virReportError(VIR_ERR_XML_ERROR, "%s",
4aa5c4
+                       _("Failed to parse memory allocation threads"));
4aa5c4
+        return -1;
4aa5c4
+    }
4aa5c4
+
4aa5c4
     if (virXPathNode("./memoryBacking/hugepages", ctxt)) {
4aa5c4
         /* hugepages will be used */
4aa5c4
         if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt, &nodes)) < 0) {
4aa5c4
@@ -27639,6 +27646,7 @@ virDomainMemorybackingFormat(virBuffer *buf,
4aa5c4
                              const virDomainMemtune *mem)
4aa5c4
 {
4aa5c4
     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
4aa5c4
+    g_auto(virBuffer) allocAttrBuf = VIR_BUFFER_INITIALIZER;
4aa5c4
 
4aa5c4
     if (mem->nhugepages)
4aa5c4
         virDomainHugepagesFormat(&childBuf, mem->hugepages, mem->nhugepages);
4aa5c4
@@ -27653,8 +27661,13 @@ virDomainMemorybackingFormat(virBuffer *buf,
4aa5c4
         virBufferAsprintf(&childBuf, "<access mode='%s'/>\n",
4aa5c4
                           virDomainMemoryAccessTypeToString(mem->access));
4aa5c4
     if (mem->allocation)
4aa5c4
-        virBufferAsprintf(&childBuf, "<allocation mode='%s'/>\n",
4aa5c4
+        virBufferAsprintf(&allocAttrBuf, " mode='%s'",
4aa5c4
                           virDomainMemoryAllocationTypeToString(mem->allocation));
4aa5c4
+    if (mem->allocation_threads > 0)
4aa5c4
+        virBufferAsprintf(&allocAttrBuf, " threads='%u'", mem->allocation_threads);
4aa5c4
+
4aa5c4
+    virXMLFormatElement(&childBuf, "allocation", &allocAttrBuf, NULL);
4aa5c4
+
4aa5c4
     if (mem->discard)
4aa5c4
         virBufferAddLit(&childBuf, "<discard/>\n");
4aa5c4
 
4aa5c4
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
4aa5c4
index 144ba4dd12..10af94e2e4 100644
4aa5c4
--- a/src/conf/domain_conf.h
4aa5c4
+++ b/src/conf/domain_conf.h
4aa5c4
@@ -2677,6 +2677,7 @@ struct _virDomainMemtune {
4aa5c4
     int source; /* enum virDomainMemorySource */
4aa5c4
     int access; /* enum virDomainMemoryAccess */
4aa5c4
     int allocation; /* enum virDomainMemoryAllocation */
4aa5c4
+    unsigned int allocation_threads;
4aa5c4
 
4aa5c4
     virTristateBool discard;
4aa5c4
 };
4aa5c4
diff --git a/tests/qemuxml2argvdata/memfd-memory-numa.xml b/tests/qemuxml2argvdata/memfd-memory-numa.xml
4aa5c4
index 1ebcee8939..1ac87e3aef 100644
4aa5c4
--- a/tests/qemuxml2argvdata/memfd-memory-numa.xml
4aa5c4
+++ b/tests/qemuxml2argvdata/memfd-memory-numa.xml
4aa5c4
@@ -10,7 +10,7 @@
4aa5c4
     </hugepages>
4aa5c4
     <source type='memfd'/>
4aa5c4
     <access mode='shared'/>
4aa5c4
-    <allocation mode='immediate'/>
4aa5c4
+    <allocation mode='immediate' threads='8'/>
4aa5c4
   </memoryBacking>
4aa5c4
   <vcpu placement='static'>8</vcpu>
4aa5c4
   <numatune>
4aa5c4
-- 
4aa5c4
2.35.1
4aa5c4