diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 072f9a0fdcb58840142de2a9a14039dd41d61300..80172c18d0c25ee94fe4c46bb7943f8d1f32c6c6 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1016,6 +1016,7 @@ <source type="file|anonymous"/> <access mode="shared|private"/> <allocation mode="immediate|ondemand"/> + <discard/> </memoryBacking> ... </domain> @@ -1070,6 +1071,14 @@ numa node by memAccess
allocation
Specify when allocate the 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 this is + just an optimization and is not guaranteed to work in + all cases (e.g. when hypervisor crashes). + Since 4.4.0 (QEMU/KVM only) +
@@ -1608,7 +1617,7 @@ <cpu> ... <numa> - <cell id='0' cpus='0-3' memory='512000' unit='KiB'/> + <cell id='0' cpus='0-3' memory='512000' unit='KiB' discard='yes'/> <cell id='1' cpus='4-7' memory='512000' unit='KiB' memAccess='shared'/> </numa> ... @@ -1634,6 +1643,13 @@ memAccess can control whether the memory is to be mapped as "shared" or "private". This is valid only for hugepages-backed memory and nvdimm modules. + + Each cell element can have an optional + discard attribute which fine tunes the discard + feature for given numa node as described under + Memory Backing. + Accepted values are yes and no. + Since 4.4.0

@@ -7883,7 +7899,7 @@ qemu-kvm -net nic,model=? /dev/null

 ...
 <devices>
-  <memory model='dimm' access='private'>
+  <memory model='dimm' access='private' discard='yes'>
     <target>
       <size unit='KiB'>524287</size>
       <node>0</node>
@@ -7937,6 +7953,20 @@ qemu-kvm -net nic,model=? /dev/null
         

+
discard
+
+

+ An optional attribute discard + (since 4.4.0) that provides + capability to fine tune discard of data on per module + basis. Accepted values are yes and + no. The feature is described here: + Memory Backing. + This attribute is allowed only for + model='dimm'. +

+
+
source

diff --git a/docs/schemas/cputypes.rng b/docs/schemas/cputypes.rng index c45b6dfb28adf7ffe82ac4c429dadf423609e53a..1f1e0e36d59bf60ebd0a349f720a9001ded8fd17 100644 --- a/docs/schemas/cputypes.rng +++ b/docs/schemas/cputypes.rng @@ -129,6 +129,11 @@ + + + + + diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 8c446ca41856901e22722c19500c0a65360821d4..13af5b74a4988ecd4076e5235e5c6dcdbaef9f53 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -633,6 +633,11 @@ + + + + + @@ -5124,6 +5129,11 @@ + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6786d81c9b0a6014d5496661c68b3958af641417..86229db654f98da12ae2d3e857c64deb850e22da 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5516,6 +5516,20 @@ virDomainVideoDefValidate(const virDomainVideoDef *video) } +static int +virDomainMemoryDefValidate(const virDomainMemoryDef *mem) +{ + if (mem->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM && + mem->discard == VIR_TRISTATE_BOOL_YES) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("discard is not supported for nvdimms")); + return -1; + } + + return 0; +} + + static int virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, const virDomainDef *def) @@ -5548,6 +5562,9 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_VIDEO: return virDomainVideoDefValidate(dev->data.video); + case VIR_DOMAIN_DEVICE_MEMORY: + return virDomainMemoryDefValidate(dev->data.memory); + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: @@ -5560,7 +5577,6 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: - case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: @@ -15673,6 +15689,16 @@ virDomainMemoryDefParseXML(virDomainXMLOptionPtr xmlopt, } VIR_FREE(tmp); + if ((tmp = virXMLPropString(memdevNode, "discard"))) { + if ((val = virTristateBoolTypeFromString(tmp)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid discard value '%s'"), tmp); + goto error; + } + + def->discard = val; + } + /* source */ if ((node = virXPathNode("./source", ctxt)) && virDomainMemorySourceDefParseXML(node, ctxt, def) < 0) @@ -18999,6 +19025,9 @@ virDomainDefParseXML(xmlDocPtr xml, if (virXPathBoolean("boolean(./memoryBacking/locked)", ctxt)) def->mem.locked = true; + if (virXPathBoolean("boolean(./memoryBacking/discard)", ctxt)) + def->mem.discard = VIR_TRISTATE_BOOL_YES; + /* Extract blkio cgroup tunables */ if (virXPathUInt("string(./blkiotune/weight)", ctxt, &def->blkio.weight) < 0) @@ -25259,6 +25288,9 @@ virDomainMemoryDefFormat(virBufferPtr buf, if (def->access) virBufferAsprintf(buf, " access='%s'", virDomainMemoryAccessTypeToString(def->access)); + if (def->discard) + virBufferAsprintf(buf, " discard='%s'", + virTristateBoolTypeToString(def->discard)); virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); @@ -26605,6 +26637,8 @@ virDomainMemtuneFormat(virBufferPtr buf, if (mem->allocation) virBufferAsprintf(&childBuf, "\n", virDomainMemoryAllocationTypeToString(mem->allocation)); + if (mem->discard) + virBufferAddLit(&childBuf, "\n"); if (virXMLFormatElement(buf, "memoryBacking", NULL, &childBuf) < 0) goto cleanup; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 15d228ba9e62780bd6192cb01c25f14c7cf8665d..07d04fb2f986db29b908dbea8c61319dbd9a67d5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2105,6 +2105,7 @@ typedef enum { struct _virDomainMemoryDef { virDomainMemoryAccess access; + virTristateBool discard; /* source */ virBitmapPtr sourceNodes; @@ -2267,6 +2268,8 @@ struct _virDomainMemtune { int source; /* enum virDomainMemorySource */ int access; /* enum virDomainMemoryAccess */ int allocation; /* enum virDomainMemoryAllocation */ + + virTristateBool discard; }; typedef struct _virDomainPowerManagement virDomainPowerManagement; diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c index 9307dd93d3d47ceab9bbdc530a131b81e1548100..97a3ca485d178cad3e5bfe9d469673737b422de0 100644 --- a/src/conf/numa_conf.c +++ b/src/conf/numa_conf.c @@ -77,6 +77,7 @@ struct _virDomainNuma { virBitmapPtr nodeset; /* host memory nodes where this guest node resides */ virDomainNumatuneMemMode mode; /* memory mode selection */ virDomainMemoryAccess memAccess; /* shared memory access configuration */ + virTristateBool discard; /* discard-data for memory-backend-file */ struct _virDomainNumaDistance { unsigned int value; /* locality value for node i->j or j->i */ @@ -947,6 +948,18 @@ virDomainNumaDefCPUParseXML(virDomainNumaPtr def, VIR_FREE(tmp); } + if ((tmp = virXMLPropString(nodes[i], "discard"))) { + if ((rc = virTristateBoolTypeFromString(tmp)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Invalid 'discard' attribute value '%s'"), + tmp); + goto cleanup; + } + + def->mem_nodes[cur_cell].discard = rc; + VIR_FREE(tmp); + } + /* Parse NUMA distances info */ if (virDomainNumaDefNodeDistanceParseXML(def, ctxt, cur_cell) < 0) goto cleanup; @@ -967,6 +980,7 @@ virDomainNumaDefCPUFormatXML(virBufferPtr buf, virDomainNumaPtr def) { virDomainMemoryAccess memAccess; + virTristateBool discard; char *cpustr; size_t ncells = virDomainNumaGetNodeCount(def); size_t i; @@ -980,6 +994,7 @@ virDomainNumaDefCPUFormatXML(virBufferPtr buf, int ndistances; memAccess = virDomainNumaGetNodeMemoryAccessMode(def, i); + discard = virDomainNumaGetNodeDiscard(def, i); if (!(cpustr = virBitmapFormat(virDomainNumaGetNodeCpumask(def, i)))) return -1; @@ -994,6 +1009,10 @@ virDomainNumaDefCPUFormatXML(virBufferPtr buf, virBufferAsprintf(buf, " memAccess='%s'", virDomainMemoryAccessTypeToString(memAccess)); + if (discard) + virBufferAsprintf(buf, " discard='%s'", + virTristateBoolTypeToString(discard)); + ndistances = def->mem_nodes[i].ndistances; if (ndistances == 0) { virBufferAddLit(buf, "/>\n"); @@ -1304,6 +1323,14 @@ virDomainNumaGetNodeMemoryAccessMode(virDomainNumaPtr numa, } +virTristateBool +virDomainNumaGetNodeDiscard(virDomainNumaPtr numa, + size_t node) +{ + return numa->mem_nodes[node].discard; +} + + unsigned long long virDomainNumaGetNodeMemorySize(virDomainNumaPtr numa, size_t node) diff --git a/src/conf/numa_conf.h b/src/conf/numa_conf.h index 7947fdb21923bc2c80b42fb27afc46b73cf1551b..85269be5651284216b39062ecdf38acf9cbf517a 100644 --- a/src/conf/numa_conf.h +++ b/src/conf/numa_conf.h @@ -102,6 +102,9 @@ virBitmapPtr virDomainNumaGetNodeCpumask(virDomainNumaPtr numa, virDomainMemoryAccess virDomainNumaGetNodeMemoryAccessMode(virDomainNumaPtr numa, size_t node) ATTRIBUTE_NONNULL(1); +virTristateBool virDomainNumaGetNodeDiscard(virDomainNumaPtr numa, + size_t node) + ATTRIBUTE_NONNULL(1); unsigned long long virDomainNumaGetNodeMemorySize(virDomainNumaPtr numa, size_t node) ATTRIBUTE_NONNULL(1); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5fea1bca41d9a58eb8002664be1c26995ddcd143..d28a751ebd1ae836e4303bf17533f19d7c83d5a1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -750,6 +750,7 @@ virDomainNumaGetMaxCPUID; virDomainNumaGetMemorySize; virDomainNumaGetNodeCount; virDomainNumaGetNodeCpumask; +virDomainNumaGetNodeDiscard; virDomainNumaGetNodeDistance; virDomainNumaGetNodeMemoryAccessMode; virDomainNumaGetNodeMemorySize; diff --git a/tests/qemuxml2argvdata/hugepages-pages.xml b/tests/qemuxml2argvdata/hugepages-pages.xml index f9270782d4fe12d564363dd422ef27d115b79097..cba83e754c295939d167da9596d898e366ca2b17 100644 --- a/tests/qemuxml2argvdata/hugepages-pages.xml +++ b/tests/qemuxml2argvdata/hugepages-pages.xml @@ -8,6 +8,7 @@ + 4 @@ -21,7 +22,7 @@ - + diff --git a/tests/qemuxml2argvdata/hugepages-pages3.xml b/tests/qemuxml2argvdata/hugepages-pages3.xml index 3d3b3f3cc3fcb0e3a138f8291edfe3de6dbc937a..147acc4c95a627742b985b9f08fed42198742232 100644 --- a/tests/qemuxml2argvdata/hugepages-pages3.xml +++ b/tests/qemuxml2argvdata/hugepages-pages3.xml @@ -15,8 +15,8 @@ - - + + diff --git a/tests/qemuxml2argvdata/hugepages-pages7.xml b/tests/qemuxml2argvdata/hugepages-pages7.xml index d75cf5afa343c75eab85417efc43aa735d72b1ab..28c72f85a72d644bb196623b4644aa984fdafe1d 100644 --- a/tests/qemuxml2argvdata/hugepages-pages7.xml +++ b/tests/qemuxml2argvdata/hugepages-pages7.xml @@ -43,7 +43,7 @@

- + 1-3 1048576 @@ -54,7 +54,7 @@
- + 524287 0 diff --git a/tests/qemuxml2xmloutdata/hugepages-pages.xml b/tests/qemuxml2xmloutdata/hugepages-pages.xml index 498610a217fed837e62f6fa2d455a7e048a2ca1d..292454588e556536429f23bdfdc57b6bfda4b053 100644 --- a/tests/qemuxml2xmloutdata/hugepages-pages.xml +++ b/tests/qemuxml2xmloutdata/hugepages-pages.xml @@ -8,6 +8,7 @@ + 4 @@ -21,7 +22,7 @@ - + diff --git a/tests/qemuxml2xmloutdata/hugepages-pages3.xml b/tests/qemuxml2xmloutdata/hugepages-pages3.xml index be21c3eddd9332f09b40da7f20fa706a61cf712d..90e6efa5eaca5e48f6d1f2b558d49e2142d84a92 100644 --- a/tests/qemuxml2xmloutdata/hugepages-pages3.xml +++ b/tests/qemuxml2xmloutdata/hugepages-pages3.xml @@ -15,8 +15,8 @@ - - + +