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@xxxxxxxxxx> --- 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