[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/2] qemu: New XML to disable memory merge at guest startup



QEMU introduced command line "-mem-merge=on|off" (defaults to on) to
enable/disable the memory merge (KSM) at guest startup. This exposes
it by new XML:
  <memoryBacking>
    <nosharepages/>
  </memoryBacking>

The XML tag is same with what we used internally for old RHEL.
---
 docs/formatdomain.html.in                          | 13 ++++++---
 docs/schemas/domaincommon.rng                      |  5 ++++
 src/conf/domain_conf.c                             | 20 +++++++++-----
 src/conf/domain_conf.h                             |  1 +
 src/qemu/qemu_command.c                            | 22 +++++++++++++++
 tests/qemuargv2xmltest.c                           |  2 ++
 .../qemuxml2argv-nosharepages.args                 |  4 +++
 .../qemuxml2argvdata/qemuxml2argv-nosharepages.xml | 31 ++++++++++++++++++++++
 tests/qemuxml2argvtest.c                           |  1 +
 tests/qemuxml2xmltest.c                            |  1 +
 10 files changed, 90 insertions(+), 10 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 9ade507..3a6c18f 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -561,6 +561,7 @@
   ...
   &lt;memoryBacking&gt;
     &lt;hugepages/&gt;
+    &lt;nosharepages/&gt;
   &lt;/memoryBacking&gt;
   ...
 &lt;/domain&gt;
@@ -568,10 +569,14 @@
 
     <dl>
       <dt><code>memoryBacking</code></dt>
-      <dd>The optional <code>memoryBacking</code> element, may have an
-        <code>hugepages</code> element set within it. This tells the
-        hypervisor that the guest should have its memory allocated using
-        hugepages instead of the normal native page size.</dd>
+      <dd>The optional <code>memoryBacking</code> element has two
+        optional elements. The element <code>hugepages</code> tells
+        the hypervisor that the guest should have its memory allocated
+        using hugepages instead of the normal native page size. And the
+        optional element <code>nosharepages</code> tells the hypervisor
+        that share pages (memory merge, KSM) should be disabled on guest
+        startup.
+      </dd>
     </dl>
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 8004428..2e0e28e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -495,6 +495,11 @@
               <empty/>
             </element>
           </optional>
+          <optional>
+            <element name="nosharepages">
+              <empty/>
+            </element>
+          </optional>
         </element>
       </optional>
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 862b997..2ab1bf8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10306,6 +10306,9 @@ virDomainDefParseXML(xmlDocPtr xml,
     if ((node = virXPathNode("./memoryBacking/hugepages", ctxt)))
         def->mem.hugepage_backed = true;
 
+    if ((node = virXPathNode("./memoryBacking/nosharepages", ctxt)))
+        def->mem.nosharepages = true;
+
     /* Extract blkio cgroup tunables */
     if (virXPathUInt("string(./blkiotune/weight)", ctxt,
                      &def->blkio.weight) < 0)
@@ -15662,12 +15665,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
         def->mem.swap_hard_limit)
         virBufferAddLit(buf, "  </memtune>\n");
 
-    if (def->mem.hugepage_backed) {
-        virBufferStrcat(buf,
-                        "  <memoryBacking>\n",
-                        "    <hugepages/>\n",
-                        "  </memoryBacking>\n", NULL);
-    }
+    if (def->mem.hugepage_backed || def->mem.nosharepages)
+        virBufferAddLit(buf, "  <memoryBacking>\n");
+
+    if (def->mem.hugepage_backed)
+        virBufferAddLit(buf, "    <hugepages/>\n");
+
+    if (def->mem.nosharepages)
+        virBufferAddLit(buf, "    <nosharepages/>\n");
+
+    if (def->mem.hugepage_backed || def->mem.nosharepages)
+        virBufferAddLit(buf, "  </memoryBacking>\n");
 
     virBufferAddLit(buf, "  <vcpu");
     virBufferAsprintf(buf, " placement='%s'",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a9d3410..1151111 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1850,6 +1850,7 @@ struct _virDomainDef {
         unsigned long long max_balloon; /* in kibibytes */
         unsigned long long cur_balloon; /* in kibibytes */
         bool hugepage_backed;
+        bool nosharepages;
         int dump_core; /* enum virDomainMemDump */
         unsigned long long hard_limit; /* in kibibytes */
         unsigned long long soft_limit; /* in kibibytes */
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index eddc263..a9d71de 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5838,6 +5838,14 @@ qemuBuildMachineArgStr(virCommandPtr cmd,
                              "with this QEMU binary"));
             return -1;
         }
+
+        if (def->mem.nosharepages) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("disable shared memory is not available "
+                             "with this QEMU binary"));
+             return -1;
+        }
+
         obsoleteAccel = true;
     } else {
         virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -5871,6 +5879,18 @@ qemuBuildMachineArgStr(virCommandPtr cmd,
                               virDomainMemDumpTypeToString(def->mem.dump_core));
         }
 
+        if (def->mem.nosharepages) {
+            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_MERGE)) {
+                virBufferAddLit(&buf, ",mem-merge=off");
+            } else {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("disable shared memory is not available "
+                                 "with this QEMU binary"));
+                virBufferFreeAndReset(&buf);
+                return -1;
+            }
+        }
+
         virCommandAddArgBuffer(cmd, &buf);
     }
 
@@ -10176,6 +10196,8 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps,
                             def->mem.dump_core = VIR_DOMAIN_MEM_DUMP_DEFAULT;
                         if (params)
                             VIR_FREE(tmp);
+                    } else if (STRPREFIX(tmp, "mem-merge=off")) {
+                        def->mem.nosharepages = true;
                     }
                 }
             }
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 005aa0c..528b8bf 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -246,6 +246,8 @@ mymain(void)
 
     DO_TEST("pseries-nvram");
 
+    DO_TEST("nosharepages");
+
     DO_TEST_FULL("restore-v1", 0, "stdio");
     DO_TEST_FULL("restore-v2", 0, "stdio");
     DO_TEST_FULL("restore-v2", 0, "exec:cat");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args
new file mode 100644
index 0000000..a32dfe5
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S -machine pc,accel=tcg,mem-merge=off -m 215 -smp 1 -nographic \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi \
+-boot c -usb -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml
new file mode 100644
index 0000000..5e54cd0
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml
@@ -0,0 +1,31 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219200</memory>
+  <currentMemory unit='KiB'>219200</currentMemory>
+  <memoryBacking>
+    <nosharepages/>
+  </memoryBacking>
+  <vcpu placement='static'>1</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>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <controller type='pci' index='0' model='pci-root'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 98ceb83..a45fa9a 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -436,6 +436,7 @@ mymain(void)
     DO_TEST("hyperv", NONE);
 
     DO_TEST("hugepages", QEMU_CAPS_MEM_PATH);
+    DO_TEST("nosharepages", QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_MEM_MERGE);
     DO_TEST("disk-cdrom", NONE);
     DO_TEST("disk-cdrom-empty", QEMU_CAPS_DRIVE);
     DO_TEST("disk-cdrom-tray",
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 492ac60..ddf3230 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -158,6 +158,7 @@ mymain(void)
     DO_TEST("hyperv");
 
     DO_TEST("hugepages");
+    DO_TEST("nosharepages");
     DO_TEST("disk-aio");
     DO_TEST("disk-cdrom");
     DO_TEST("disk-floppy");
-- 
1.8.1.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]