Since its commit v5.0.0-rc0~75^2~1^2~3 QEMU is capable of
specifying number of threads used to allocate memory. While it
defaults to the number of vCPUs, users might want to use a
different value (especially for humongous guests with gigantic
pages).
In general, on QEMU cmd line level it is possible to use
different number of threads per each memory-backend-* object, in
practical terms it's not useful. Therefore, use <memoryBacking/>
to set guest wide value and let all memory devices 'inherit' it,
silently. IOW, don't introduce per device knob because that would
only complicate things for a little or no benefit.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
docs/formatdomain.rst | 6 ++++--
docs/schemas/domaincommon.rng | 19 +++++++++++++------
src/conf/domain_conf.c | 15 ++++++++++++++-
src/conf/domain_conf.h | 1 +
tests/qemuxml2argvdata/memfd-memory-numa.xml | 2 +-
5 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 9b1b69bb4d..8e25474db0 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -1004,7 +1004,7 @@ Memory Backing
<locked/>
<source type="file|anonymous|memfd"/>
<access mode="shared|private"/>
- <allocation mode="immediate|ondemand"/>
+ <allocation mode="immediate|ondemand" threads='8'/>
<discard/>
</memoryBacking>
...
@@ -1054,7 +1054,9 @@ influence how virtual memory pages are backed by host pages.
"private". This can be overridden per numa node by ``memAccess``.
``allocation``
Using the ``mode`` attribute, specify when to allocate the memory by
- supplying either "immediate" or "ondemand".
+ supplying either "immediate" or "ondemand". :since:`Since 8.2.0`
this
+ attribute is optional among with ``threads`` attribute, that sets the number
+ of threads that hypervisor uses to allocate memory.
``discard``
When set and supported by hypervisor the memory content is discarded just
before guest shuts down (or when DIMM module is unplugged). Please note that
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9c1b64a644..34bccee2f5 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -740,12 +740,19 @@
</optional>
<optional>
<element name="allocation">
- <attribute name="mode">
- <choice>
- <value>immediate</value>
- <value>ondemand</value>
- </choice>
- </attribute>
+ <optional>
+ <attribute name="mode">
+ <choice>
+ <value>immediate</value>
+ <value>ondemand</value>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="threads">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </optional>
</element>
</optional>
<optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e0dfc9e45f..2414a806d0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -18914,6 +18914,13 @@ virDomainDefParseMemory(virDomainDef *def,
VIR_FREE(tmp);
}
+ if (virXPathUInt("string(./memoryBacking/allocation/@threads)",
+ ctxt, &def->mem.allocation_threads) == -2) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Failed to parse memory allocation threads"));
+ return -1;
+ }
+
if (virXPathNode("./memoryBacking/hugepages", ctxt)) {
/* hugepages will be used */
if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt,
&nodes)) < 0) {
@@ -27464,6 +27471,7 @@ virDomainMemorybackingFormat(virBuffer *buf,
const virDomainMemtune *mem)
{
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
+ g_auto(virBuffer) allocAttrBuf = VIR_BUFFER_INITIALIZER;
if (mem->nhugepages)
virDomainHugepagesFormat(&childBuf, mem->hugepages, mem->nhugepages);
@@ -27478,8 +27486,13 @@ virDomainMemorybackingFormat(virBuffer *buf,
virBufferAsprintf(&childBuf, "<access
mode='%s'/>\n",
virDomainMemoryAccessTypeToString(mem->access));
if (mem->allocation)
- virBufferAsprintf(&childBuf, "<allocation
mode='%s'/>\n",
+ virBufferAsprintf(&allocAttrBuf, " mode='%s'",
virDomainMemoryAllocationTypeToString(mem->allocation));
+ if (mem->allocation_threads)
+ virBufferAsprintf(&allocAttrBuf, " threads='%u'",
mem->allocation_threads);
+
+ virXMLFormatElement(&childBuf, "allocation", &allocAttrBuf, NULL);
+
if (mem->discard)
virBufferAddLit(&childBuf, "<discard/>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a4de46773c..48df6cc389 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2701,6 +2701,7 @@ struct _virDomainMemtune {
int source; /* enum virDomainMemorySource */
int access; /* enum virDomainMemoryAccess */
int allocation; /* enum virDomainMemoryAllocation */
+ unsigned int allocation_threads;
virTristateBool discard;
};
diff --git a/tests/qemuxml2argvdata/memfd-memory-numa.xml
b/tests/qemuxml2argvdata/memfd-memory-numa.xml
index 1ebcee8939..1ac87e3aef 100644
--- a/tests/qemuxml2argvdata/memfd-memory-numa.xml
+++ b/tests/qemuxml2argvdata/memfd-memory-numa.xml
@@ -10,7 +10,7 @@
</hugepages>
<source type='memfd'/>
<access mode='shared'/>
- <allocation mode='immediate'/>
+ <allocation mode='immediate' threads='8'/>
</memoryBacking>
<vcpu placement='static'>8</vcpu>
<numatune>
--
2.34.1