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