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

Daniel Henrique Barboza danielhb413 at gmail.com
Wed Dec 2 14:44:39 UTC 2020


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




More information about the libvir-list mailing list