conf: Introduce memoryBacking/discard

QEMU has possibility to call madvise(.., MADV_REMOVE) in some
cases. Expose this feature to users by new element/attribute
discard.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Michal Privoznik 2018-05-11 15:08:53 +02:00
parent 0329075733
commit 2300c92fe0
13 changed files with 126 additions and 11 deletions

View File

@ -1016,6 +1016,7 @@
&lt;source type="file|anonymous"/&gt; &lt;source type="file|anonymous"/&gt;
&lt;access mode="shared|private"/&gt; &lt;access mode="shared|private"/&gt;
&lt;allocation mode="immediate|ondemand"/&gt; &lt;allocation mode="immediate|ondemand"/&gt;
&lt;discard/&gt;
&lt;/memoryBacking&gt; &lt;/memoryBacking&gt;
... ...
&lt;/domain&gt; &lt;/domain&gt;
@ -1070,6 +1071,14 @@
numa node by <code>memAccess</code></dd> numa node by <code>memAccess</code></dd>
<dt><code>allocation</code></dt> <dt><code>allocation</code></dt>
<dd>Specify when allocate the memory</dd> <dd>Specify when allocate the memory</dd>
<dt><code>discard</code></dt>
<dd>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).
<span class="since">Since 4.4.0</span> (QEMU/KVM only)
</dd>
</dl> </dl>
@ -1608,7 +1617,7 @@
&lt;cpu&gt; &lt;cpu&gt;
... ...
&lt;numa&gt; &lt;numa&gt;
&lt;cell id='0' cpus='0-3' memory='512000' unit='KiB'/&gt; &lt;cell id='0' cpus='0-3' memory='512000' unit='KiB' discard='yes'/&gt;
&lt;cell id='1' cpus='4-7' memory='512000' unit='KiB' memAccess='shared'/&gt; &lt;cell id='1' cpus='4-7' memory='512000' unit='KiB' memAccess='shared'/&gt;
&lt;/numa&gt; &lt;/numa&gt;
... ...
@ -1634,6 +1643,13 @@
<code>memAccess</code> can control whether the memory is to be <code>memAccess</code> can control whether the memory is to be
mapped as "shared" or "private". This is valid only for mapped as "shared" or "private". This is valid only for
hugepages-backed memory and nvdimm modules. hugepages-backed memory and nvdimm modules.
Each <code>cell</code> element can have an optional
<code>discard</code> attribute which fine tunes the discard
feature for given numa node as described under
<a href="#elementsMemoryBacking">Memory Backing</a>.
Accepted values are <code>yes</code> and <code>no</code>.
<span class='since'>Since 4.4.0</span>
</p> </p>
<p> <p>
@ -7883,7 +7899,7 @@ qemu-kvm -net nic,model=? /dev/null
<pre> <pre>
... ...
&lt;devices&gt; &lt;devices&gt;
&lt;memory model='dimm' access='private'&gt; &lt;memory model='dimm' access='private' discard='yes'&gt;
&lt;target&gt; &lt;target&gt;
&lt;size unit='KiB'&gt;524287&lt;/size&gt; &lt;size unit='KiB'&gt;524287&lt;/size&gt;
&lt;node&gt;0&lt;/node&gt; &lt;node&gt;0&lt;/node&gt;
@ -7937,6 +7953,20 @@ qemu-kvm -net nic,model=? /dev/null
</p> </p>
</dd> </dd>
<dt><code>discard</code></dt>
<dd>
<p>
An optional attribute <code>discard</code>
(<span class="since">since 4.4.0</span>) that provides
capability to fine tune discard of data on per module
basis. Accepted values are <code>yes</code> and
<code>no</code>. The feature is described here:
<a href="#elementsMemoryBacking">Memory Backing</a>.
This attribute is allowed only for
<code>model='dimm'</code>.
</p>
</dd>
<dt><code>source</code></dt> <dt><code>source</code></dt>
<dd> <dd>
<p> <p>

View File

@ -129,6 +129,11 @@
</choice> </choice>
</attribute> </attribute>
</optional> </optional>
<optional>
<attribute name="discard">
<ref name="virYesNo"/>
</attribute>
</optional>
<optional> <optional>
<element name="distances"> <element name="distances">
<oneOrMore> <oneOrMore>

View File

@ -633,6 +633,11 @@
</attribute> </attribute>
</element> </element>
</optional> </optional>
<optional>
<element name="discard">
<empty/>
</element>
</optional>
</interleave> </interleave>
</element> </element>
</optional> </optional>
@ -5124,6 +5129,11 @@
</choice> </choice>
</attribute> </attribute>
</optional> </optional>
<optional>
<attribute name="discard">
<ref name="virYesNo"/>
</attribute>
</optional>
<interleave> <interleave>
<optional> <optional>
<ref name="memorydev-source"/> <ref name="memorydev-source"/>

View File

@ -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 static int
virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
const virDomainDef *def) const virDomainDef *def)
@ -5548,6 +5562,9 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
case VIR_DOMAIN_DEVICE_VIDEO: case VIR_DOMAIN_DEVICE_VIDEO:
return virDomainVideoDefValidate(dev->data.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_LEASE:
case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_FS:
case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_INPUT:
@ -5560,7 +5577,6 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_MEMORY:
case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_IOMMU:
case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_LAST:
@ -15673,6 +15689,16 @@ virDomainMemoryDefParseXML(virDomainXMLOptionPtr xmlopt,
} }
VIR_FREE(tmp); 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 */ /* source */
if ((node = virXPathNode("./source", ctxt)) && if ((node = virXPathNode("./source", ctxt)) &&
virDomainMemorySourceDefParseXML(node, ctxt, def) < 0) virDomainMemorySourceDefParseXML(node, ctxt, def) < 0)
@ -18999,6 +19025,9 @@ virDomainDefParseXML(xmlDocPtr xml,
if (virXPathBoolean("boolean(./memoryBacking/locked)", ctxt)) if (virXPathBoolean("boolean(./memoryBacking/locked)", ctxt))
def->mem.locked = true; def->mem.locked = true;
if (virXPathBoolean("boolean(./memoryBacking/discard)", ctxt))
def->mem.discard = VIR_TRISTATE_BOOL_YES;
/* Extract blkio cgroup tunables */ /* Extract blkio cgroup tunables */
if (virXPathUInt("string(./blkiotune/weight)", ctxt, if (virXPathUInt("string(./blkiotune/weight)", ctxt,
&def->blkio.weight) < 0) &def->blkio.weight) < 0)
@ -25259,6 +25288,9 @@ virDomainMemoryDefFormat(virBufferPtr buf,
if (def->access) if (def->access)
virBufferAsprintf(buf, " access='%s'", virBufferAsprintf(buf, " access='%s'",
virDomainMemoryAccessTypeToString(def->access)); virDomainMemoryAccessTypeToString(def->access));
if (def->discard)
virBufferAsprintf(buf, " discard='%s'",
virTristateBoolTypeToString(def->discard));
virBufferAddLit(buf, ">\n"); virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2); virBufferAdjustIndent(buf, 2);
@ -26605,6 +26637,8 @@ virDomainMemtuneFormat(virBufferPtr buf,
if (mem->allocation) if (mem->allocation)
virBufferAsprintf(&childBuf, "<allocation mode='%s'/>\n", virBufferAsprintf(&childBuf, "<allocation mode='%s'/>\n",
virDomainMemoryAllocationTypeToString(mem->allocation)); virDomainMemoryAllocationTypeToString(mem->allocation));
if (mem->discard)
virBufferAddLit(&childBuf, "<discard/>\n");
if (virXMLFormatElement(buf, "memoryBacking", NULL, &childBuf) < 0) if (virXMLFormatElement(buf, "memoryBacking", NULL, &childBuf) < 0)
goto cleanup; goto cleanup;

View File

@ -2105,6 +2105,7 @@ typedef enum {
struct _virDomainMemoryDef { struct _virDomainMemoryDef {
virDomainMemoryAccess access; virDomainMemoryAccess access;
virTristateBool discard;
/* source */ /* source */
virBitmapPtr sourceNodes; virBitmapPtr sourceNodes;
@ -2267,6 +2268,8 @@ struct _virDomainMemtune {
int source; /* enum virDomainMemorySource */ int source; /* enum virDomainMemorySource */
int access; /* enum virDomainMemoryAccess */ int access; /* enum virDomainMemoryAccess */
int allocation; /* enum virDomainMemoryAllocation */ int allocation; /* enum virDomainMemoryAllocation */
virTristateBool discard;
}; };
typedef struct _virDomainPowerManagement virDomainPowerManagement; typedef struct _virDomainPowerManagement virDomainPowerManagement;

View File

@ -77,6 +77,7 @@ struct _virDomainNuma {
virBitmapPtr nodeset; /* host memory nodes where this guest node resides */ virBitmapPtr nodeset; /* host memory nodes where this guest node resides */
virDomainNumatuneMemMode mode; /* memory mode selection */ virDomainNumatuneMemMode mode; /* memory mode selection */
virDomainMemoryAccess memAccess; /* shared memory access configuration */ virDomainMemoryAccess memAccess; /* shared memory access configuration */
virTristateBool discard; /* discard-data for memory-backend-file */
struct _virDomainNumaDistance { struct _virDomainNumaDistance {
unsigned int value; /* locality value for node i->j or j->i */ unsigned int value; /* locality value for node i->j or j->i */
@ -947,6 +948,18 @@ virDomainNumaDefCPUParseXML(virDomainNumaPtr def,
VIR_FREE(tmp); 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 */ /* Parse NUMA distances info */
if (virDomainNumaDefNodeDistanceParseXML(def, ctxt, cur_cell) < 0) if (virDomainNumaDefNodeDistanceParseXML(def, ctxt, cur_cell) < 0)
goto cleanup; goto cleanup;
@ -967,6 +980,7 @@ virDomainNumaDefCPUFormatXML(virBufferPtr buf,
virDomainNumaPtr def) virDomainNumaPtr def)
{ {
virDomainMemoryAccess memAccess; virDomainMemoryAccess memAccess;
virTristateBool discard;
char *cpustr; char *cpustr;
size_t ncells = virDomainNumaGetNodeCount(def); size_t ncells = virDomainNumaGetNodeCount(def);
size_t i; size_t i;
@ -980,6 +994,7 @@ virDomainNumaDefCPUFormatXML(virBufferPtr buf,
int ndistances; int ndistances;
memAccess = virDomainNumaGetNodeMemoryAccessMode(def, i); memAccess = virDomainNumaGetNodeMemoryAccessMode(def, i);
discard = virDomainNumaGetNodeDiscard(def, i);
if (!(cpustr = virBitmapFormat(virDomainNumaGetNodeCpumask(def, i)))) if (!(cpustr = virBitmapFormat(virDomainNumaGetNodeCpumask(def, i))))
return -1; return -1;
@ -994,6 +1009,10 @@ virDomainNumaDefCPUFormatXML(virBufferPtr buf,
virBufferAsprintf(buf, " memAccess='%s'", virBufferAsprintf(buf, " memAccess='%s'",
virDomainMemoryAccessTypeToString(memAccess)); virDomainMemoryAccessTypeToString(memAccess));
if (discard)
virBufferAsprintf(buf, " discard='%s'",
virTristateBoolTypeToString(discard));
ndistances = def->mem_nodes[i].ndistances; ndistances = def->mem_nodes[i].ndistances;
if (ndistances == 0) { if (ndistances == 0) {
virBufferAddLit(buf, "/>\n"); 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 unsigned long long
virDomainNumaGetNodeMemorySize(virDomainNumaPtr numa, virDomainNumaGetNodeMemorySize(virDomainNumaPtr numa,
size_t node) size_t node)

View File

@ -102,6 +102,9 @@ virBitmapPtr virDomainNumaGetNodeCpumask(virDomainNumaPtr numa,
virDomainMemoryAccess virDomainNumaGetNodeMemoryAccessMode(virDomainNumaPtr numa, virDomainMemoryAccess virDomainNumaGetNodeMemoryAccessMode(virDomainNumaPtr numa,
size_t node) size_t node)
ATTRIBUTE_NONNULL(1); ATTRIBUTE_NONNULL(1);
virTristateBool virDomainNumaGetNodeDiscard(virDomainNumaPtr numa,
size_t node)
ATTRIBUTE_NONNULL(1);
unsigned long long virDomainNumaGetNodeMemorySize(virDomainNumaPtr numa, unsigned long long virDomainNumaGetNodeMemorySize(virDomainNumaPtr numa,
size_t node) size_t node)
ATTRIBUTE_NONNULL(1); ATTRIBUTE_NONNULL(1);

View File

@ -750,6 +750,7 @@ virDomainNumaGetMaxCPUID;
virDomainNumaGetMemorySize; virDomainNumaGetMemorySize;
virDomainNumaGetNodeCount; virDomainNumaGetNodeCount;
virDomainNumaGetNodeCpumask; virDomainNumaGetNodeCpumask;
virDomainNumaGetNodeDiscard;
virDomainNumaGetNodeDistance; virDomainNumaGetNodeDistance;
virDomainNumaGetNodeMemoryAccessMode; virDomainNumaGetNodeMemoryAccessMode;
virDomainNumaGetNodeMemorySize; virDomainNumaGetNodeMemorySize;

View File

@ -8,6 +8,7 @@
<page size='2048' unit='KiB' nodeset='1'/> <page size='2048' unit='KiB' nodeset='1'/>
<page size='1048576' unit='KiB' nodeset='0,2-3'/> <page size='1048576' unit='KiB' nodeset='0,2-3'/>
</hugepages> </hugepages>
<discard/>
</memoryBacking> </memoryBacking>
<vcpu placement='static'>4</vcpu> <vcpu placement='static'>4</vcpu>
<numatune> <numatune>
@ -21,7 +22,7 @@
<cpu> <cpu>
<numa> <numa>
<cell id='0' cpus='0' memory='1048576' unit='KiB'/> <cell id='0' cpus='0' memory='1048576' unit='KiB'/>
<cell id='1' cpus='1' memory='1048576' unit='KiB'/> <cell id='1' cpus='1' memory='1048576' unit='KiB' discard='no'/>
<cell id='2' cpus='2' memory='1048576' unit='KiB'/> <cell id='2' cpus='2' memory='1048576' unit='KiB'/>
<cell id='3' cpus='3' memory='1048576' unit='KiB'/> <cell id='3' cpus='3' memory='1048576' unit='KiB'/>
</numa> </numa>

View File

@ -15,8 +15,8 @@
</os> </os>
<cpu> <cpu>
<numa> <numa>
<cell id='0' cpus='0' memory='262144' unit='KiB'/> <cell id='0' cpus='0' memory='262144' unit='KiB' discard='no'/>
<cell id='1' cpus='1' memory='786432' unit='KiB'/> <cell id='1' cpus='1' memory='786432' unit='KiB' discard='yes'/>
</numa> </numa>
</cpu> </cpu>
<clock offset='utc'/> <clock offset='utc'/>

View File

@ -43,7 +43,7 @@
<memballoon model='virtio'> <memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</memballoon> </memballoon>
<memory model='dimm'> <memory model='dimm' discard='no'>
<source> <source>
<nodemask>1-3</nodemask> <nodemask>1-3</nodemask>
<pagesize unit='KiB'>1048576</pagesize> <pagesize unit='KiB'>1048576</pagesize>
@ -54,7 +54,7 @@
</target> </target>
<address type='dimm' slot='0'/> <address type='dimm' slot='0'/>
</memory> </memory>
<memory model='dimm' access='private'> <memory model='dimm' access='private' discard='yes'>
<target> <target>
<size unit='KiB'>524287</size> <size unit='KiB'>524287</size>
<node>0</node> <node>0</node>

View File

@ -8,6 +8,7 @@
<page size='2048' unit='KiB' nodeset='1'/> <page size='2048' unit='KiB' nodeset='1'/>
<page size='1048576' unit='KiB' nodeset='0,2-3'/> <page size='1048576' unit='KiB' nodeset='0,2-3'/>
</hugepages> </hugepages>
<discard/>
</memoryBacking> </memoryBacking>
<vcpu placement='static'>4</vcpu> <vcpu placement='static'>4</vcpu>
<numatune> <numatune>
@ -21,7 +22,7 @@
<cpu> <cpu>
<numa> <numa>
<cell id='0' cpus='0' memory='1048576' unit='KiB'/> <cell id='0' cpus='0' memory='1048576' unit='KiB'/>
<cell id='1' cpus='1' memory='1048576' unit='KiB'/> <cell id='1' cpus='1' memory='1048576' unit='KiB' discard='no'/>
<cell id='2' cpus='2' memory='1048576' unit='KiB'/> <cell id='2' cpus='2' memory='1048576' unit='KiB'/>
<cell id='3' cpus='3' memory='1048576' unit='KiB'/> <cell id='3' cpus='3' memory='1048576' unit='KiB'/>
</numa> </numa>

View File

@ -15,8 +15,8 @@
</os> </os>
<cpu> <cpu>
<numa> <numa>
<cell id='0' cpus='0' memory='262144' unit='KiB'/> <cell id='0' cpus='0' memory='262144' unit='KiB' discard='no'/>
<cell id='1' cpus='1' memory='786432' unit='KiB'/> <cell id='1' cpus='1' memory='786432' unit='KiB' discard='yes'/>
</numa> </numa>
</cpu> </cpu>
<clock offset='utc'/> <clock offset='utc'/>