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;access mode="shared|private"/&gt;
&lt;allocation mode="immediate|ondemand"/&gt;
&lt;discard/&gt;
&lt;/memoryBacking&gt;
...
&lt;/domain&gt;
@ -1070,6 +1071,14 @@
numa node by <code>memAccess</code></dd>
<dt><code>allocation</code></dt>
<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>
@ -1608,7 +1617,7 @@
&lt;cpu&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;/numa&gt;
...
@ -1634,6 +1643,13 @@
<code>memAccess</code> 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 <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>
@ -7883,7 +7899,7 @@ qemu-kvm -net nic,model=? /dev/null
<pre>
...
&lt;devices&gt;
&lt;memory model='dimm' access='private'&gt;
&lt;memory model='dimm' access='private' discard='yes'&gt;
&lt;target&gt;
&lt;size unit='KiB'&gt;524287&lt;/size&gt;
&lt;node&gt;0&lt;/node&gt;
@ -7937,6 +7953,20 @@ qemu-kvm -net nic,model=? /dev/null
</p>
</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>
<dd>
<p>

View File

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

View File

@ -633,6 +633,11 @@
</attribute>
</element>
</optional>
<optional>
<element name="discard">
<empty/>
</element>
</optional>
</interleave>
</element>
</optional>
@ -5124,6 +5129,11 @@
</choice>
</attribute>
</optional>
<optional>
<attribute name="discard">
<ref name="virYesNo"/>
</attribute>
</optional>
<interleave>
<optional>
<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
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, "<allocation mode='%s'/>\n",
virDomainMemoryAllocationTypeToString(mem->allocation));
if (mem->discard)
virBufferAddLit(&childBuf, "<discard/>\n");
if (virXMLFormatElement(buf, "memoryBacking", NULL, &childBuf) < 0)
goto cleanup;

View File

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

View File

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

View File

@ -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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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