|
|
abb18f |
From e60a964e51cb0aecb060f1a1cc2884586e00ddeb Mon Sep 17 00:00:00 2001
|
|
|
abb18f |
Message-Id: <e60a964e51cb0aecb060f1a1cc2884586e00ddeb@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)
|
|
|
abb18f |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2075569
|
|
|
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 |
|