Re: [PATCH v1 1/1] support system default memory policy with numatune

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

 



Apologies for the late review.

First, 'ninja -C build test' complained about long lines in
the numatune-memory-migratable.x86_64-latest.args file. I amended
it here and the tests passed:


$ git diff
diff --git a/tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args b/tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args
index 6a99540792..1f15c4396e 100644
--- a/tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args
+++ b/tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args
@@ -6,12 +6,16 @@ LOGNAME=test \
 XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest/.local/share \
 XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest/.cache \
 XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest/.config \
-QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
 -name guest=QEMUGuest,debug-threads=on \
 -S \
--object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest/master-key.aes \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-QEMUGuest/master-key.aes \
 -machine pc,accel=tcg,usb=off,dump-guest-core=off \
--cpu qemu64 -m 24105 -overcommit mem-lock=off \
+-cpu qemu64 \
+-m 24105 \
+-overcommit mem-lock=off \
 -smp 32,sockets=32,cores=1,threads=1 \
 -object memory-backend-ram,id=ram-node0,size=20971520 \
 -numa node,nodeid=0,cpus=0,memdev=ram-node0 \
@@ -31,5 +35,6 @@ QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 \
 -boot strict=on \
 -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
--sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
 -msg timestamp=on


So there's already something to be fixed in the next version.


More comments below:




On 11/3/20 8:15 AM, Luyao Zhong wrote:
This patch seeks the support of system default memory policy
when numatune is configured. Before this patch, numatune only
has three memory modes: static, interleave and prefered.
These memory policies are ultimately set by mbind() system call.

Memory policy could be 'hard coded' into the kernel, but none of
above policies fit our requirment under this case. mbind() support

s/requirment/requirement

default memory policy, but it requires a NULL nodemask. So obviously
setting allowed memory nodes is cgroups' mission. That means if
'default' mode is specified in numatune, numatune config will be
completely cgroups setting, which restricting the memory
nodes allowed for each vcpu thread in different cells.

<numatune>
    <memory mode="default" nodeset="1-4,^3" migratable="yes" />
    <memnode cellid="0" mode="default" nodeset="1"/>
    <memnode cellid="2" mode="default" nodeset="2"/>
</numatune>

If you want to set default memory policy, please set migratable to
"yes" and mode to "default" at the same time.

Some implementation details are not determained, so this patch

s/determained/determined

is not split into logical blocks yet.


IIUC 'migratable' always implies mode='default' for all memnode cells. In
this case I find it a bit redundant to have both 'migratable' and 'default'
settings to care about. At the same time I was not able to come up with
something clever/better: having just the 'migratable' attribute and
simply assume 'mode=default' for all memnodes would be confusing. I guess
the extra verbosity of having to set both is justified in this case.


---
  docs/formatdomain.rst                         | 12 ++++-
  docs/schemas/domaincommon.rng                 |  7 +++
  include/libvirt/libvirt-domain.h              |  1 +
  src/conf/numa_conf.c                          | 50 ++++++++++++++++++-
  src/conf/numa_conf.h                          |  2 +
  src/libvirt_private.syms                      |  1 +
  src/qemu/qemu_command.c                       |  7 ++-
  src/qemu/qemu_process.c                       | 25 ++++++++++
  src/util/virnuma.c                            |  3 ++
  .../numatune-memory-migratable.args           | 34 +++++++++++++
  ...atune-memory-migratable.x86_64-latest.args | 35 +++++++++++++
  .../numatune-memory-migratable.xml            | 33 ++++++++++++
  tests/qemuxml2argvtest.c                      |  2 +
  ...matune-memory-migratable.x86_64-latest.xml | 40 +++++++++++++++
  .../numatune-memory-migratable.xml            | 39 +++++++++++++++
  tests/qemuxml2xmltest.c                       |  1 +
  16 files changed, 288 insertions(+), 4 deletions(-)
  create mode 100644 tests/qemuxml2argvdata/numatune-memory-migratable.args
  create mode 100644 tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args
  create mode 100644 tests/qemuxml2argvdata/numatune-memory-migratable.xml
  create mode 100644 tests/qemuxml2xmloutdata/numatune-memory-migratable.x86_64-latest.xml
  create mode 100644 tests/qemuxml2xmloutdata/numatune-memory-migratable.xml

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index ae635bedff..4ab9873c32 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -1086,8 +1086,9 @@ NUMA Node Tuning
  ``memory``
     The optional ``memory`` element specifies how to allocate memory for the
     domain process on a NUMA host. It contains several optional attributes.
-   Attribute ``mode`` is either 'interleave', 'strict', or 'preferred', defaults
-   to 'strict'. Attribute ``nodeset`` specifies the NUMA nodes, using the same
+   Attribute ``mode`` is either 'interleave', 'strict', 'preferred' or 'default',
+   defaults to 'strict', 'default' specifies that memory policy is system
+   default policy. Attribute ``nodeset`` specifies the NUMA nodes, using the same
     syntax as attribute ``cpuset`` of element ``vcpu``. Attribute ``placement`` (
     :since:`since 0.9.12` ) can be used to indicate the memory placement mode for
     domain process, its value can be either "static" or "auto", defaults to
@@ -1097,6 +1098,13 @@ NUMA Node Tuning
     will be ignored if it's specified. If ``placement`` of ``vcpu`` is 'auto',
     and ``numatune`` is not specified, a default ``numatune`` with ``placement``
     'auto' and ``mode`` 'strict' will be added implicitly. :since:`Since 0.9.3`
+   Attribute ``migratable`` is 'no' by default, and 'yes' indicates that it
+   allows operating system or hypervisor migrating the memory pages between
+   different memory nodes according to system default policy, that also means
+   we will not rely on mbind() or set_mempolicy() system calls to set the memory
+   policy or memory affinity, we only use cgroups to restrict the initial memory
+   allocation. So if ``migratable`` is 'yes', the ``mode`` is required to set to
+   'default'

You need to mention, either here or in the 'memnode' subsection right after, that
migratable='yes' implies that all memnodes must be set to mode='default' too.

.
  ``memnode``
     Optional ``memnode`` elements can specify memory allocation policies per each
     guest NUMA node. For those nodes having no corresponding ``memnode`` element,
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index a62a598568..546566df41 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1085,12 +1085,18 @@
        <interleave>
          <optional>
            <element name="memory">
+            <optional>
+              <attribute name="migratable">
+                <ref name="virYesNo"/>
+              </attribute>
+            </optional>
              <optional>
                <attribute name="mode">
                  <choice>
                    <value>strict</value>
                    <value>preferred</value>
                    <value>interleave</value>
+                  <value>default</value>
                  </choice>
                </attribute>
              </optional>
@@ -1123,6 +1129,7 @@
                  <value>strict</value>
                  <value>preferred</value>
                  <value>interleave</value>
+                <value>default</value>
                </choice>
              </attribute>
              <attribute name="nodeset">
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index b3310729bf..28f3346e07 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1527,6 +1527,7 @@ typedef enum {
      VIR_DOMAIN_NUMATUNE_MEM_STRICT      = 0,
      VIR_DOMAIN_NUMATUNE_MEM_PREFERRED   = 1,
      VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE  = 2,
+    VIR_DOMAIN_NUMATUNE_MEM_DEFAULT = 3,
# ifdef VIR_ENUM_SENTINELS
      VIR_DOMAIN_NUMATUNE_MEM_LAST /* This constant is subject to change */
diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c
index f8a7a01ac9..b299e7d8fc 100644
--- a/src/conf/numa_conf.c
+++ b/src/conf/numa_conf.c
@@ -43,6 +43,7 @@ VIR_ENUM_IMPL(virDomainNumatuneMemMode,
                "strict",
                "preferred",
                "interleave",
+              "default",
  );
VIR_ENUM_IMPL(virDomainNumatunePlacement,
@@ -99,6 +100,7 @@ struct _virDomainNuma {
          virBitmapPtr nodeset;
          virDomainNumatuneMemMode mode;
          virDomainNumatunePlacement placement;
+        virTristateBool migratable;
      } memory;               /* pinning for all the memory */
struct _virDomainNumaNode {
@@ -234,10 +236,18 @@ virDomainNumatuneNodeParseXML(virDomainNumaPtr numa,
                                 _("Invalid mode attribute in memnode element"));
                  goto cleanup;
              }
-            VIR_FREE(tmp);
              mem_node->mode = mode;
          }
+ if ((numa->memory.migratable == VIR_TRISTATE_BOOL_YES) &&
+            (mem_node->mode != VIR_DOMAIN_NUMATUNE_MEM_DEFAULT)) {
+            virReportError(VIR_ERR_XML_ERROR,
+                               _("Invalid 'mode' attribute value '%s' when "
+                                 "'migratable' is 'yes', 'default' is required"), tmp);
+            goto cleanup;
+        }
+        VIR_FREE(tmp);
+
          tmp = virXMLPropString(cur_node, "nodeset");
          if (!tmp) {
              virReportError(VIR_ERR_XML_ERROR, "%s",
@@ -275,6 +285,7 @@ virDomainNumatuneParseXML(virDomainNumaPtr numa,
      int ret = -1;
      virBitmapPtr nodeset = NULL;
      xmlNodePtr node = NULL;
+    int migratable = 0;
if (virXPathInt("count(./numatune)", ctxt, &n) < 0) {
          virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -292,11 +303,27 @@ virDomainNumatuneParseXML(virDomainNumaPtr numa,
          placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO;
if (node) {
+        if ((tmp = virXMLPropString(node, "migratable")) &&
+            (migratable = virTristateBoolTypeFromString(tmp)) <= 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid 'migratable' attribute value '%s'"), tmp);
+            goto cleanup;
+        }
+        numa->memory.migratable = migratable;
+        VIR_FREE(tmp);
+
          if ((tmp = virXMLPropString(node, "mode")) &&
              (mode = virDomainNumatuneMemModeTypeFromString(tmp)) < 0) {
              virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                             _("Unsupported NUMA memory tuning mode '%s'"), tmp);
              goto cleanup;
+        } else if (migratable == VIR_TRISTATE_BOOL_YES) {
+            if ((tmp == NULL) || (mode != VIR_DOMAIN_NUMATUNE_MEM_DEFAULT)) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("Invalid 'mode' attribute value '%s' when "
+                                 "'migratable' is 'yes', 'default' is required"), tmp);
+                goto cleanup;
+            }
          }
          VIR_FREE(tmp);
@@ -369,6 +396,11 @@ virDomainNumatuneFormatXML(virBufferPtr buf,
          tmp = virDomainNumatuneMemModeTypeToString(numatune->memory.mode);
          virBufferAsprintf(buf, "<memory mode='%s' ", tmp);
+ if (numatune->memory.migratable != VIR_TRISTATE_BOOL_ABSENT) {
+            tmp = virTristateBoolTypeToString(numatune->memory.migratable);
+            virBufferAsprintf(buf, "migratable='%s' ", tmp);
+        }
+
          if (numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC) {
              if (!(nodeset = virBitmapFormat(numatune->memory.nodeset)))
                  return -1;
@@ -427,6 +459,22 @@ virDomainNumaFree(virDomainNumaPtr numa)
      VIR_FREE(numa);
  }
+/**
+ * virDomainNumatuneGetMigratable:
+ * @numatune: pointer to numatune definition
+ *
+ * Get the migratable attribute for domain's memory.
+ *
+ * Returns: migratable value
+ */
+int virDomainNumatuneGetMigratable(virDomainNumaPtr numatune)
+{
+    if (!numatune)
+        return VIR_TRISTATE_BOOL_ABSENT;
+
+    return numatune->memory.migratable;
+}
+
  /**
   * virDomainNumatuneGetMode:
   * @numatune: pointer to numatune definition
diff --git a/src/conf/numa_conf.h b/src/conf/numa_conf.h
index db5d79e62a..d58d0c2352 100644
--- a/src/conf/numa_conf.h
+++ b/src/conf/numa_conf.h
@@ -102,6 +102,8 @@ int virDomainNumatuneFormatXML(virBufferPtr buf, virDomainNumaPtr numatune)
  /*
   * Getters
   */
+int virDomainNumatuneGetMigratable(virDomainNumaPtr numatune);
+
  int virDomainNumatuneGetMode(virDomainNumaPtr numatune,
                               int cellid,
                               virDomainNumatuneMemMode *mode);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 95e50835ad..69676b9bd1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -878,6 +878,7 @@ virDomainNumaSetNodeDistanceCount;
  virDomainNumaSetNodeMemorySize;
  virDomainNumatuneFormatNodeset;
  virDomainNumatuneFormatXML;
+virDomainNumatuneGetMigratable;
  virDomainNumatuneGetMode;
  virDomainNumatuneGetNodeset;
  virDomainNumatuneHasPerNodeBinding;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7847706594..6f3b4aecf6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -174,6 +174,7 @@ VIR_ENUM_IMPL(qemuNumaPolicy,
                "bind",
                "preferred",
                "interleave",
+              "default",
  );
@@ -3095,7 +3096,11 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
              return -1;
      }
- if (nodemask) {
+    /* If migratable attribute is yes, we should only use cgroups setting
+     * memory affinity, and skip passing the host-nodes and policy parameters
+     * to QEMU command line. */
+    if (nodemask &&
+        virDomainNumatuneGetMigratable(def->numa) != VIR_TRISTATE_BOOL_YES) {
          if (!virNumaNodesetIsAvailable(nodemask))
              return -1;
          if (virJSONValueObjectAdd(props,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index cd0f57da97..e7eeb1e928 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2713,6 +2713,7 @@ qemuProcessSetupPid(virDomainObjPtr vm,
      g_autoptr(virBitmap) hostcpumap = NULL;
      g_autofree char *mem_mask = NULL;
      int ret = -1;
+    size_t i;
if ((period || quota) &&
          !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
@@ -2753,6 +2754,30 @@ qemuProcessSetupPid(virDomainObjPtr vm,
                                                  &mem_mask, -1) < 0)
              goto cleanup;
+ /* For vCPU threads, mem_mask is different among cells and mem_mask
+         * is used to set cgroups cpuset.mems for vcpu threads. Then If we
+         * allow orperate system to migrate pages between nodes, cgroups can

s/orperate/operate

+         * restrict memory allocation from the right node at the beginning
+         * for vcpu thread. */
+        if (nameval == VIR_CGROUP_THREAD_VCPU) {
+            virDomainNumaPtr numatune = vm->def->numa;
+            virBitmapPtr numanode_cpumask = NULL;
+            for (i = 0; i < virDomainNumaGetNodeCount(numatune); i++) {
+                numanode_cpumask = virDomainNumaGetNodeCpumask(numatune, i);
+                /* 'i' indicates the cell id, if the vCPU id is in this cell,
+                 * we need get the corresonding nodeset. */

s/corresonding/corresponding





Thanks,



DHB

+                if (virBitmapIsBitSet(numanode_cpumask, id)) {
+                    if (virDomainNumatuneMaybeFormatNodeset(numatune,
+                                                            priv->autoNodeset,
+                                                            &mem_mask, i) < 0) {
+                        goto cleanup;
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+
          if (virCgroupNewThread(priv->cgroup, nameval, id, true, &cgroup) < 0)
              goto cleanup;
diff --git a/src/util/virnuma.c b/src/util/virnuma.c
index 5d40d13977..5fb9c79921 100644
--- a/src/util/virnuma.c
+++ b/src/util/virnuma.c
@@ -152,6 +152,9 @@ virNumaSetupMemoryPolicy(virDomainNumatuneMemMode mode,
          numa_set_interleave_mask(&mask);
          break;
+ case VIR_DOMAIN_NUMATUNE_MEM_DEFAULT:
+        break;
+
      case VIR_DOMAIN_NUMATUNE_MEM_LAST:
          break;
      }
diff --git a/tests/qemuxml2argvdata/numatune-memory-migratable.args b/tests/qemuxml2argvdata/numatune-memory-migratable.args
new file mode 100644
index 0000000000..62300d72a2
--- /dev/null
+++ b/tests/qemuxml2argvdata/numatune-memory-migratable.args
@@ -0,0 +1,34 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest/.config \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest \
+-S \
+-machine pc,accel=tcg,usb=off,dump-guest-core=off \
+-m 24105 \
+-realtime mlock=off \
+-smp 32,sockets=32,cores=1,threads=1 \
+-object memory-backend-ram,id=ram-node0,size=20971520 \
+-numa node,nodeid=0,cpus=0,memdev=ram-node0 \
+-object memory-backend-ram,id=ram-node1,size=676331520 \
+-numa node,nodeid=1,cpus=1-27,cpus=29,memdev=ram-node1 \
+-object memory-backend-ram,id=ram-node2,size=24578621440 \
+-numa node,nodeid=2,cpus=28,cpus=30-31,memdev=ram-node2 \
+-uuid 9f4b6512-e73a-4a25-93e8-5307802821ce \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args b/tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args
new file mode 100644
index 0000000000..6a99540792
--- /dev/null
+++ b/tests/qemuxml2argvdata/numatune-memory-migratable.x86_64-latest.args
@@ -0,0 +1,35 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest/.config \
+QEMU_AUDIO_DRV=none /usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,file=/tmp/lib/domain--1-QEMUGuest/master-key.aes \
+-machine pc,accel=tcg,usb=off,dump-guest-core=off \
+-cpu qemu64 -m 24105 -overcommit mem-lock=off \
+-smp 32,sockets=32,cores=1,threads=1 \
+-object memory-backend-ram,id=ram-node0,size=20971520 \
+-numa node,nodeid=0,cpus=0,memdev=ram-node0 \
+-object memory-backend-ram,id=ram-node1,size=676331520 \
+-numa node,nodeid=1,cpus=1-27,cpus=29,memdev=ram-node1 \
+-object memory-backend-ram,id=ram-node2,size=24578621440 \
+-numa node,nodeid=2,cpus=28,cpus=30-31,memdev=ram-node2 \
+-uuid 9f4b6512-e73a-4a25-93e8-5307802821ce \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/numatune-memory-migratable.xml b/tests/qemuxml2argvdata/numatune-memory-migratable.xml
new file mode 100644
index 0000000000..c3f83dfa25
--- /dev/null
+++ b/tests/qemuxml2argvdata/numatune-memory-migratable.xml
@@ -0,0 +1,33 @@
+<domain type='qemu'>
+  <name>QEMUGuest</name>
+  <uuid>9f4b6512-e73a-4a25-93e8-5307802821ce</uuid>
+  <memory unit='KiB'>24682468</memory>
+  <currentMemory unit='KiB'>24682468</currentMemory>
+  <vcpu placement='static'>32</vcpu>
+  <numatune>
+    <memory mode='default' nodeset='0-7' migratable="yes"/>
+    <memnode cellid='0' mode='default' nodeset='3'/>
+    <memnode cellid='2' mode='default' nodeset='1-2,5-7,^6'/>
+  </numatune>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <cpu>
+    <numa>
+      <cell id='0' cpus='0' memory='20002' unit='KiB'/>
+      <cell id='1' cpus='1-27,29' memory='660066' unit='KiB'/>
+      <cell id='2' cpus='28,30-31' memory='24002400' unit='KiB'/>
+    </numa>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' 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 ef8a871a19..1bcd0d525d 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1987,6 +1987,8 @@ mymain(void)
DO_TEST("numatune-memory", NONE);
      DO_TEST_PARSE_ERROR("numatune-memory-invalid-nodeset", NONE);
+    DO_TEST_CAPS_LATEST("numatune-memory-migratable");
+
      DO_TEST("numatune-memnode",
              QEMU_CAPS_NUMA,
              QEMU_CAPS_OBJECT_MEMORY_RAM);
diff --git a/tests/qemuxml2xmloutdata/numatune-memory-migratable.x86_64-latest.xml b/tests/qemuxml2xmloutdata/numatune-memory-migratable.x86_64-latest.xml
new file mode 100644
index 0000000000..8460843b33
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/numatune-memory-migratable.x86_64-latest.xml
@@ -0,0 +1,40 @@
+<domain type='qemu'>
+  <name>QEMUGuest</name>
+  <uuid>9f4b6512-e73a-4a25-93e8-5307802821ce</uuid>
+  <memory unit='KiB'>24682468</memory>
+  <currentMemory unit='KiB'>24682468</currentMemory>
+  <vcpu placement='static'>32</vcpu>
+  <numatune>
+    <memory mode='default' migratable='yes' nodeset='0-7'/>
+    <memnode cellid='0' mode='default' nodeset='3'/>
+    <memnode cellid='2' mode='default' nodeset='1-2,5,7'/>
+  </numatune>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+    <numa>
+      <cell id='0' cpus='0' memory='20002' unit='KiB'/>
+      <cell id='1' cpus='1-27,29' memory='660066' unit='KiB'/>
+      <cell id='2' cpus='28,30-31' memory='24002400' unit='KiB'/>
+    </numa>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <controller type='usb' index='0' model='piix3-uhci'>
+      <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='0x02' function='0x0'/>
+    </memballoon>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/numatune-memory-migratable.xml b/tests/qemuxml2xmloutdata/numatune-memory-migratable.xml
new file mode 100644
index 0000000000..92a7c028ee
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/numatune-memory-migratable.xml
@@ -0,0 +1,39 @@
+<domain type='qemu'>
+  <name>QEMUGuest</name>
+  <uuid>9f4b6512-e73a-4a25-93e8-5307802821ce</uuid>
+  <memory unit='KiB'>24682468</memory>
+  <currentMemory unit='KiB'>24682468</currentMemory>
+  <vcpu placement='static'>32</vcpu>
+  <numatune>
+    <memory mode='default' migratable='yes' nodeset='0-7'/>
+    <memnode cellid='0' mode='default' nodeset='3'/>
+    <memnode cellid='2' mode='default' nodeset='1-2,5,7'/>
+  </numatune>
+  <os>
+    <type arch='x86_64' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <cpu>
+    <numa>
+      <cell id='0' cpus='0' memory='20002' unit='KiB'/>
+      <cell id='1' cpus='1-27,29' memory='660066' unit='KiB'/>
+      <cell id='2' cpus='28,30-31' memory='24002400' unit='KiB'/>
+    </numa>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 44ac9fbce7..a3d5a18b57 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1147,6 +1147,7 @@ mymain(void)
      DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST);
      DO_TEST("numatune-no-vcpu", QEMU_CAPS_NUMA);
      DO_TEST("numatune-hmat", QEMU_CAPS_NUMA_HMAT, QEMU_CAPS_OBJECT_MEMORY_RAM);
+    DO_TEST_CAPS_LATEST("numatune-memory-migratable");
DO_TEST("bios-nvram", NONE);
      DO_TEST("bios-nvram-os-interleave", NONE);





[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux