]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: Add new xml elements for file memorybacking support
authorJaroslav Safka <jaroslavx.safka@intel.com>
Thu, 2 Feb 2017 13:27:32 +0000 (13:27 +0000)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 9 Feb 2017 13:27:19 +0000 (14:27 +0100)
This part introduces new xml elements for file based
memorybacking support and their parsing.
(It allows vhost-user to be used without hugepages.)

New xml elements:
<memoryBacking>
  <source type="file|anonymous"/>
  <access mode="shared|private"/>
  <allocation mode="immediate|ondemand"/>
</memoryBacking>

docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml [new file with mode: 0644]
tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml [new file with mode: 0644]
tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml [new file with mode: 0644]
tests/qemuxml2xmltest.c

index 77d8e718996d0070b3dcadb1ad24588d588bdb8b..0a115f5dcda80140c3569db060a0f9c782824162 100644 (file)
     &lt;/hugepages&gt;
     &lt;nosharepages/&gt;
     &lt;locked/&gt;
+    &lt;source type="file|anonymous"/&gt;
+    &lt;access mode="shared|private"/&gt;
+    &lt;allocation mode="immediate|ondemand"/&gt;
   &lt;/memoryBacking&gt;
   ...
 &lt;/domain&gt;
         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. <span class="since">Since 1.0.6</span></dd>
+       <dt><code>source</code></dt>
+       <dd>In this attribute you can switch to file memorybacking or keep default anonymous.</dd>
+       <dt><code>access</code></dt>
+       <dd>Specify if memory is shared or private. This can be overridden per numa node by <code>memAccess</code></dd>
+       <dt><code>allocation</code></dt>
+       <dd>Specify when allocate the memory</dd>
     </dl>
 
 
index cc6e0d0c0d653e9465e2f65c77dc852e1af2706f..d715bff29d05d8152572503c5cf44791c6e5688a 100644 (file)
                 <empty/>
               </element>
             </optional>
+            <optional>
+              <element name="source">
+                <attribute name="type">
+                  <choice>
+                    <value>file</value>
+                    <value>anonymous</value>
+                  </choice>
+                </attribute>
+              </element>
+            </optional>
+            <optional>
+              <element name="access">
+                <attribute name="mode">
+                  <choice>
+                    <value>shared</value>
+                    <value>private</value>
+                  </choice>
+                </attribute>
+              </element>
+            </optional>
+            <optional>
+              <element name="allocation">
+                <attribute name="mode">
+                  <choice>
+                    <value>immediate</value>
+                    <value>ondemand</value>
+                  </choice>
+                </attribute>
+              </element>
+            </optional>
           </interleave>
         </element>
       </optional>
index c06b128ddcb459b0e8f1c73172fe466d5b6570d5..ba55791a0454731bab4d9b4d45a38df61096f77e 100644 (file)
@@ -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)
+    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);
+    }
+
+    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;
+        }
+
+        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;
-            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);
+            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 {
-        if ((node = virXPathNode("./memoryBacking/hugepages", ctxt))) {
+            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, "</memtune>\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, "<memoryBacking>\n");
         virBufferAdjustIndent(buf, 2);
         if (def->mem.nhugepages)
@@ -23737,6 +23794,16 @@ virDomainDefFormatInternal(virDomainDefPtr def,
             virBufferAddLit(buf, "<nosharepages/>\n");
         if (def->mem.locked)
             virBufferAddLit(buf, "<locked/>\n");
+        if (def->mem.source)
+            virBufferAsprintf(buf, "<source type='%s'/>\n",
+                virDomainMemorySourceTypeToString(def->mem.source));
+        if (def->mem.access)
+            virBufferAsprintf(buf, "<access mode='%s'/>\n",
+                virDomainMemoryAccessTypeToString(def->mem.access));
+        if (def->mem.allocation)
+            virBufferAsprintf(buf, "<allocation mode='%s'/>\n",
+                virDomainMemoryAllocationTypeToString(def->mem.allocation));
+
         virBufferAdjustIndent(buf, -2);
         virBufferAddLit(buf, "</memoryBacking>\n");
     }
index 507ace8711748f18b9b7cb56881bd9bb35d3f26a..dd79206f69f41da837aea2a79079a7caa9b436b0 100644 (file)
@@ -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 (file)
index 0000000..e23bc36
--- /dev/null
@@ -0,0 +1,24 @@
+<domain type='qemu'>
+  <name>SomeDummyGuest</name>
+  <uuid>ef1bdff4-27f3-4e85-a807-5fb4d58463cc</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <memoryBacking>
+    <source type='file'/>
+    <access mode='shared'/>
+    <allocation mode='immediate'/>
+  </memoryBacking>
+  <vcpu placement='static'>2</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml
new file mode 100644 (file)
index 0000000..6f50765
--- /dev/null
@@ -0,0 +1,24 @@
+<domain type='qemu'>
+  <name>SomeDummyGuest</name>
+  <uuid>ef1bdff4-27f3-4e85-a807-5fb4d58463cc</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <memoryBacking>
+    <source type="anonymous"/>
+    <access mode="private"/>
+    <allocation mode="ondemand"/>
+  </memoryBacking>
+  <vcpu placement='static'>2</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml
new file mode 100644 (file)
index 0000000..fb07472
--- /dev/null
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>SomeDummyGuest</name>
+  <uuid>ef1bdff4-27f3-4e85-a807-5fb4d58463cc</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <memoryBacking>
+    <source type='file'/>
+    <access mode='shared'/>
+    <allocation mode='immediate'/>
+  </memoryBacking>
+  <vcpu placement='static'>2</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </memballoon>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml
new file mode 100644 (file)
index 0000000..ac2a278
--- /dev/null
@@ -0,0 +1,32 @@
+<domain type='qemu'>
+  <name>SomeDummyGuest</name>
+  <uuid>ef1bdff4-27f3-4e85-a807-5fb4d58463cc</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <memoryBacking>
+    <source type='anonymous'/>
+    <access mode='private'/>
+    <allocation mode='ondemand'/>
+  </memoryBacking>
+  <vcpu placement='static'>2</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <controller type='usb' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='virtio'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+    </memballoon>
+  </devices>
+</domain>
index 4f3b09ae311a06435cd68bf7c2d4566d478e6175..0702f581ec09d93de38123254c2121e55f723fb0 100644 (file)
@@ -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);