diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 77d8e71899..0a115f5dcd 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -903,6 +903,9 @@
</hugepages>
<nosharepages/>
<locked/>
+ <source type="file|anonymous"/>
+ <access mode="shared|private"/>
+ <allocation mode="immediate|ondemand"/>
</memoryBacking>
...
</domain>
@@ -942,6 +945,12 @@
most of the host's memory). Doing so may be dangerous to both the
domain and the host itself since the host's kernel may run out of
memory. Since 1.0.6
+
source
+ In this attribute you can switch to file memorybacking or keep default anonymous.
+ access
+ Specify if memory is shared or private. This can be overridden per numa node by memAccess
+ allocation
+ Specify when allocate the memory
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index cc6e0d0c0d..d715bff29d 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -565,6 +565,36 @@
+
+
+
+
+ file
+ anonymous
+
+
+
+
+
+
+
+
+ shared
+ private
+
+
+
+
+
+
+
+
+ immediate
+ ondemand
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c06b128ddc..ba55791a04 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -837,6 +837,16 @@ VIR_ENUM_IMPL(virDomainDiskMirrorState, VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
"abort",
"pivot")
+VIR_ENUM_IMPL(virDomainMemorySource, VIR_DOMAIN_MEMORY_SOURCE_LAST,
+ "none",
+ "file",
+ "anonymous")
+
+VIR_ENUM_IMPL(virDomainMemoryAllocation, VIR_DOMAIN_MEMORY_ALLOCATION_LAST,
+ "none",
+ "immediate",
+ "ondemand")
+
VIR_ENUM_IMPL(virDomainLoader,
VIR_DOMAIN_LOADER_TYPE_LAST,
"rom",
@@ -16594,48 +16604,93 @@ virDomainDefParseXML(xmlDocPtr xml,
}
VIR_FREE(tmp);
- if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt, &nodes)) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("cannot extract hugepages nodes"));
- goto error;
+ tmp = virXPathString("string(./memoryBacking/source/@type)", ctxt);
+ if (tmp) {
+ if ((def->mem.source = virDomainMemorySourceTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown memoryBacking/source/type '%s'"), tmp);
+ goto error;
+ }
+ VIR_FREE(tmp);
}
- if (n) {
- if (VIR_ALLOC_N(def->mem.hugepages, n) < 0)
+ tmp = virXPathString("string(./memoryBacking/access/@mode)", ctxt);
+ if (tmp) {
+ if ((def->mem.access = virDomainMemoryAccessTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown memoryBacking/access/mode '%s'"), tmp);
goto error;
+ }
+ VIR_FREE(tmp);
+ }
- for (i = 0; i < n; i++) {
- if (virDomainHugepagesParseXML(nodes[i], ctxt,
- &def->mem.hugepages[i]) < 0)
- goto error;
- def->mem.nhugepages++;
+ tmp = virXPathString("string(./memoryBacking/allocation/@mode)", ctxt);
+ if (tmp) {
+ if ((def->mem.allocation = virDomainMemoryAllocationTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown memoryBacking/allocation/mode '%s'"), tmp);
+ goto error;
+ }
+ VIR_FREE(tmp);
+ }
- for (j = 0; j < i; j++) {
- if (def->mem.hugepages[i].nodemask &&
- def->mem.hugepages[j].nodemask &&
- virBitmapOverlaps(def->mem.hugepages[i].nodemask,
- def->mem.hugepages[j].nodemask)) {
- virReportError(VIR_ERR_XML_DETAIL,
- _("nodeset attribute of hugepages "
- "of sizes %llu and %llu intersect"),
- def->mem.hugepages[i].size,
- def->mem.hugepages[j].size);
- goto error;
- } else if (!def->mem.hugepages[i].nodemask &&
- !def->mem.hugepages[j].nodemask) {
- virReportError(VIR_ERR_XML_DETAIL,
- _("two master hugepages detected: "
- "%llu and %llu"),
- def->mem.hugepages[i].size,
- def->mem.hugepages[j].size);
- goto error;
- }
- }
+ if (virXPathNode("./memoryBacking/hugepages", ctxt)) {
+ /* hugepages will be used */
+
+ if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_ONDEMAND) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("hugepages are not allowed with memory allocation ondemand"));
+ goto error;
}
- VIR_FREE(nodes);
- } else {
- if ((node = virXPathNode("./memoryBacking/hugepages", ctxt))) {
+ if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_ANONYMOUS) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("hugepages are not allowed with anonymous memory source"));
+ goto error;
+ }
+
+ if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt, &nodes)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot extract hugepages nodes"));
+ goto error;
+ }
+
+ if (n) {
+ if (VIR_ALLOC_N(def->mem.hugepages, n) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ if (virDomainHugepagesParseXML(nodes[i], ctxt,
+ &def->mem.hugepages[i]) < 0)
+ goto error;
+ def->mem.nhugepages++;
+
+ for (j = 0; j < i; j++) {
+ if (def->mem.hugepages[i].nodemask &&
+ def->mem.hugepages[j].nodemask &&
+ virBitmapOverlaps(def->mem.hugepages[i].nodemask,
+ def->mem.hugepages[j].nodemask)) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("nodeset attribute of hugepages "
+ "of sizes %llu and %llu intersect"),
+ def->mem.hugepages[i].size,
+ def->mem.hugepages[j].size);
+ goto error;
+ } else if (!def->mem.hugepages[i].nodemask &&
+ !def->mem.hugepages[j].nodemask) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("two master hugepages detected: "
+ "%llu and %llu"),
+ def->mem.hugepages[i].size,
+ def->mem.hugepages[j].size);
+ goto error;
+ }
+ }
+ }
+
+ VIR_FREE(nodes);
+ } else {
+ /* no hugepage pages */
if (VIR_ALLOC(def->mem.hugepages) < 0)
goto error;
@@ -23728,7 +23783,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virBufferAddLit(buf, "\n");
}
- if (def->mem.nhugepages || def->mem.nosharepages || def->mem.locked) {
+ if (def->mem.nhugepages || def->mem.nosharepages || def->mem.locked
+ || def->mem.source || def->mem.access || def->mem.allocation)
+ {
virBufferAddLit(buf, "\n");
virBufferAdjustIndent(buf, 2);
if (def->mem.nhugepages)
@@ -23737,6 +23794,16 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virBufferAddLit(buf, " \n");
if (def->mem.locked)
virBufferAddLit(buf, " \n");
+ if (def->mem.source)
+ virBufferAsprintf(buf, " \n",
+ virDomainMemorySourceTypeToString(def->mem.source));
+ if (def->mem.access)
+ virBufferAsprintf(buf, " \n",
+ virDomainMemoryAccessTypeToString(def->mem.access));
+ if (def->mem.allocation)
+ virBufferAsprintf(buf, " \n",
+ virDomainMemoryAllocationTypeToString(def->mem.allocation));
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, " \n");
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 507ace8711..dd79206f69 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -586,6 +586,22 @@ typedef enum {
VIR_DOMAIN_DISK_MIRROR_STATE_LAST
} virDomainDiskMirrorState;
+typedef enum {
+ VIR_DOMAIN_MEMORY_SOURCE_NONE = 0, /* No memory source defined */
+ VIR_DOMAIN_MEMORY_SOURCE_FILE, /* Memory source is set as file */
+ VIR_DOMAIN_MEMORY_SOURCE_ANONYMOUS, /* Memory source is set as anonymous */
+
+ VIR_DOMAIN_MEMORY_SOURCE_LAST,
+} virDomainMemorySource;
+
+typedef enum {
+ VIR_DOMAIN_MEMORY_ALLOCATION_NONE = 0, /* No memory allocation defined */
+ VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE, /* Memory allocation is set as immediate */
+ VIR_DOMAIN_MEMORY_ALLOCATION_ONDEMAND, /* Memory allocation is set as ondemand */
+
+ VIR_DOMAIN_MEMORY_ALLOCATION_LAST,
+} virDomainMemoryAllocation;
+
/* Stores the virtual disk configuration */
struct _virDomainDiskDef {
@@ -2130,6 +2146,10 @@ struct _virDomainMemtune {
unsigned long long soft_limit; /* in kibibytes, limit at off_t bytes */
unsigned long long min_guarantee; /* in kibibytes, limit at off_t bytes */
unsigned long long swap_hard_limit; /* in kibibytes, limit at off_t bytes */
+
+ int source; /* enum virDomainMemorySource */
+ int access; /* enum virDomainMemoryAccess */
+ int allocation; /* enum virDomainMemoryAllocation */
};
typedef struct _virDomainPowerManagement virDomainPowerManagement;
@@ -3115,6 +3135,8 @@ VIR_ENUM_DECL(virDomainTPMModel)
VIR_ENUM_DECL(virDomainTPMBackend)
VIR_ENUM_DECL(virDomainMemoryModel)
VIR_ENUM_DECL(virDomainMemoryBackingModel)
+VIR_ENUM_DECL(virDomainMemorySource)
+VIR_ENUM_DECL(virDomainMemoryAllocation)
VIR_ENUM_DECL(virDomainIOMMUModel)
VIR_ENUM_DECL(virDomainShmemModel)
/* from libvirt.h */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml
new file mode 100644
index 0000000000..e23bc3627d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml
@@ -0,0 +1,24 @@
+
+ SomeDummyGuest
+ ef1bdff4-27f3-4e85-a807-5fb4d58463cc
+ 1048576
+ 1048576
+
+
+
+
+
+ 2
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml
new file mode 100644
index 0000000000..6f50765bba
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml
@@ -0,0 +1,24 @@
+
+ SomeDummyGuest
+ ef1bdff4-27f3-4e85-a807-5fb4d58463cc
+ 1048576
+ 1048576
+
+
+
+
+
+ 2
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml
new file mode 100644
index 0000000000..fb07472f3c
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml
@@ -0,0 +1,32 @@
+
+ SomeDummyGuest
+ ef1bdff4-27f3-4e85-a807-5fb4d58463cc
+ 1048576
+ 1048576
+
+
+
+
+
+ 2
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml
new file mode 100644
index 0000000000..ac2a278609
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml
@@ -0,0 +1,32 @@
+
+ SomeDummyGuest
+ ef1bdff4-27f3-4e85-a807-5fb4d58463cc
+ 1048576
+ 1048576
+
+
+
+
+
+ 2
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 4f3b09ae31..0702f581ec 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1042,6 +1042,9 @@ mymain(void)
DO_TEST("virtio-input", NONE);
DO_TEST("virtio-input-passthrough", NONE);
+ DO_TEST("memorybacking-set", NONE);
+ DO_TEST("memorybacking-unset", NONE);
+
virObjectUnref(cfg);
DO_TEST("acpi-table", NONE);