[libvirt] [PATCH 0/2] Add support for preallocated fd memory

Hi the xml element to be extended with additional children is the memoryBacking element. We would like to introduce 3 new elements source,access and allocation <memoryBacking> <source type="file|anonymous" path='/path/to/qemu/'/> <access Mode="shared|private"/> <allocation mode="immediate|ondemand"/> </memoryBacking> If allocation is immediate then -mem-prealloc should be added to the qemu commanline. If source is file then -object memory-backend-file,id=mem,size=1024M,mem-path=/var/lib/libvirt/qemu -numa node,memdev=mem Should be added to the qemu commandline If access is shared then the share=on parameter should be added to the memory-backend-file e.g. -object memory-backend-file,id=mem,size=1024M,mem-path=/var/lib/libvirt/qemu,share=on Jaroslav Safka (2): Add support for preallocated fd memory Add support for preallocated fd memory docs/schemas/domaincommon.rng | 37 +++++ src/conf/domain_conf.c | 149 +++++++++++++++----- src/conf/domain_conf.h | 34 +++++ src/qemu/qemu_command.c | 156 ++++++++++++++++----- src/qemu/qemu_command.h | 4 + .../qemuxml2argv-fd-memory-no-numa-topology.args | 34 +++++ .../qemuxml2argv-fd-memory-no-numa-topology.xml | 96 +++++++++++++ .../qemuxml2argv-fd-memory-numa-topology.args | 34 +++++ .../qemuxml2argv-fd-memory-numa-topology.xml | 99 +++++++++++++ .../qemuxml2argv-memorybacking-set.xml | 32 +++++ .../qemuxml2argv-memorybacking-unset.xml | 32 +++++ tests/qemuxml2argvtest.c | 24 ++++ .../qemuxml2xmlout-memorybacking-set.xml | 40 ++++++ .../qemuxml2xmlout-memorybacking-unset.xml | 40 ++++++ tests/qemuxml2xmltest.c | 3 + 15 files changed, 748 insertions(+), 66 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml -- 2.5.5 -------------------------------------------------------------- Intel Research and Development Ireland Limited Registered in Ireland Registered Office: Collinstown Industrial Park, Leixlip, County Kildare Registered Number: 308263 This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.

This first change introduces xml parsing support for preallocated shared file descriptor based memory backing. It allows vhost-user to be used without hugepages. New xml elements: <memoryBacking> <source type='file|anonymous' path='/path/to/qemu/' /> <access Mode='shared|private'/> <allocation mode='immediate|ondemand'/> </memoryBacking> --- docs/schemas/domaincommon.rng | 37 +++++ src/conf/domain_conf.c | 149 ++++++++++++++++----- src/conf/domain_conf.h | 34 +++++ .../qemuxml2argv-memorybacking-set.xml | 32 +++++ .../qemuxml2argv-memorybacking-unset.xml | 32 +++++ .../qemuxml2xmlout-memorybacking-set.xml | 40 ++++++ .../qemuxml2xmlout-memorybacking-unset.xml | 40 ++++++ tests/qemuxml2xmltest.c | 3 + 8 files changed, 334 insertions(+), 33 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 95c7882..99f93b7 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -559,6 +559,43 @@ <empty/> </element> </optional> + <optional> + <element name="source"> + <interleave> + <attribute name="type"> + <choice> + <value>file</value> + <value>anonymous</value> + </choice> + </attribute> + <optional> + <attribute name="path"> + <ref name="absFilePath"/> + </attribute> + </optional> + </interleave> + </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> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a06da46..7f73569 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -829,6 +829,21 @@ 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(virDomainMemoryAccess, VIR_DOMAIN_MEMORY_ACCESS_LAST, + "none", + "shared", + "private") + +VIR_ENUM_IMPL(virDomainMemoryAllocation, VIR_DOMAIN_MEMORY_ALLOCATION_LAST, + "none", + "immediate", + "ondemand") + VIR_ENUM_IMPL(virDomainLoader, VIR_DOMAIN_LOADER_TYPE_LAST, "rom", @@ -16179,48 +16194,101 @@ 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 (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) { + tmp = virXPathString("string(./memoryBacking/source/@path)", ctxt); + if (!tmp && VIR_STRDUP(tmp, VIR_DOMAIN_MEMORY_DEFAULT_PATH) < 0) + goto error; + + def->mem.mem_path = tmp; + tmp = NULL; + } } - 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; @@ -23447,7 +23515,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) @@ -23456,6 +23526,19 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAddLit(buf, "<nosharepages/>\n"); if (def->mem.locked) virBufferAddLit(buf, "<locked/>\n"); + if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) + virBufferAsprintf(buf, "<source type='%s' path='%s'/>\n", + virDomainMemorySourceTypeToString(def->mem.source), def->mem.mem_path); + else 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"); } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d2065cf..f1290a3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -561,6 +561,32 @@ typedef enum { VIR_DOMAIN_DISK_MIRROR_STATE_LAST } virDomainDiskMirrorState; +# define VIR_DOMAIN_MEMORY_DEFAULT_PATH "/var/lib/libvirt/qemu" + +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_ACCESS_NONE = 0, /* No memory access defined */ + VIR_DOMAIN_MEMORY_ACCESS_SHARED, /* Memory access is set as shared */ + VIR_DOMAIN_MEMORY_ACCESS_PRIVATE, /* Memory access is set as private */ + + VIR_DOMAIN_MEMORY_ACCESS_LAST, +} virDomainMemoryAccess; + +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 { @@ -2092,6 +2118,11 @@ 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 */ + char* mem_path; /* memory path when file source is selected */ }; typedef struct _virDomainPowerManagement virDomainPowerManagement; @@ -3073,6 +3104,9 @@ VIR_ENUM_DECL(virDomainTPMModel) VIR_ENUM_DECL(virDomainTPMBackend) VIR_ENUM_DECL(virDomainMemoryModel) VIR_ENUM_DECL(virDomainMemoryBackingModel) +VIR_ENUM_DECL(virDomainMemorySource) +VIR_ENUM_DECL(virDomainMemoryAccess) +VIR_ENUM_DECL(virDomainMemoryAllocation) VIR_ENUM_DECL(virDomainIOMMUModel) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) diff --git a/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml new file mode 100644 index 0000000..b48ef3a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml @@ -0,0 +1,32 @@ +<domain type='qemu'> + <name>SomeDummyHugepagesGuest</name> + <uuid>ef1bdff4-27f3-4e85-a807-5fb4d58463cc</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <memoryBacking> + <source type='file' path='/path/to/qemu'/> + <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> + <disk type='block' device='disk'> + <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/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml new file mode 100644 index 0000000..74f8a12 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml @@ -0,0 +1,32 @@ +<domain type='qemu'> + <name>SomeDummyHugepagesGuest</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> + <disk type='block' device='disk'> + <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/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml new file mode 100644 index 0000000..c17a02d --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml @@ -0,0 +1,40 @@ +<domain type='qemu'> + <name>SomeDummyHugepagesGuest</name> + <uuid>ef1bdff4-27f3-4e85-a807-5fb4d58463cc</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <memoryBacking> + <source type='file' path='/path/to/qemu'/> + <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> + <disk type='block' device='disk'> + <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'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </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 index 0000000..7de9ffb --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml @@ -0,0 +1,40 @@ +<domain type='qemu'> + <name>SomeDummyHugepagesGuest</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> + <disk type='block' device='disk'> + <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'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </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 fb05c85..e93b8b3 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -869,6 +869,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); -- 2.5.5 -------------------------------------------------------------- Intel Research and Development Ireland Limited Registered in Ireland Registered Office: Collinstown Industrial Park, Leixlip, County Kildare Registered Number: 308263 This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.

On 29.09.2016 10:56, Jaroslav Safka wrote:
This first change introduces xml parsing support for preallocated shared file descriptor based memory backing. It allows vhost-user to be used without hugepages.
New xml elements: <memoryBacking> <source type='file|anonymous' path='/path/to/qemu/' /> <access Mode='shared|private'/> <allocation mode='immediate|ondemand'/> </memoryBacking>
Okay, this is definitely interesting approach (not only because while reviewing this, I've found an old branch in my git where I've started to work on this). Frankly, I don't know if this is a good API or not. Historically, we required Dan's ACK on XML schema :-) btw: s/Mode/mode/ ;-)
--- docs/schemas/domaincommon.rng | 37 +++++ src/conf/domain_conf.c | 149 ++++++++++++++++----- src/conf/domain_conf.h | 34 +++++ .../qemuxml2argv-memorybacking-set.xml | 32 +++++ .../qemuxml2argv-memorybacking-unset.xml | 32 +++++ .../qemuxml2xmlout-memorybacking-set.xml | 40 ++++++ .../qemuxml2xmlout-memorybacking-unset.xml | 40 ++++++ tests/qemuxml2xmltest.c | 3 + 8 files changed, 334 insertions(+), 33 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml
You need to update the docs too. formatdomain.html.in to be more precise.
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a06da46..7f73569 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c
@@ -16179,48 +16194,101 @@ 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 (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) { + tmp = virXPathString("string(./memoryBacking/source/@path)", ctxt); + if (!tmp && VIR_STRDUP(tmp, VIR_DOMAIN_MEMORY_DEFAULT_PATH) < 0) + goto error; + + def->mem.mem_path = tmp; + tmp = NULL; + } }
- 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; + }
These types of checks would normally go to post parse callback.
+ + 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;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d2065cf..f1290a3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h
@@ -3073,6 +3104,9 @@ VIR_ENUM_DECL(virDomainTPMModel) VIR_ENUM_DECL(virDomainTPMBackend) VIR_ENUM_DECL(virDomainMemoryModel) VIR_ENUM_DECL(virDomainMemoryBackingModel) +VIR_ENUM_DECL(virDomainMemorySource) +VIR_ENUM_DECL(virDomainMemoryAccess) +VIR_ENUM_DECL(virDomainMemoryAllocation)
These macros declare vir*TypeFromString() and vir*TypeToString() functions. Because they are in the header file, we should update the libvirt_private.syms too (even though these functions are not used anywere else just yet). The rest of the code looks okay (even in 2/2). Michal

On Tue, Oct 04, 2016 at 05:07:16PM +0200, Michal Privoznik wrote:
On 29.09.2016 10:56, Jaroslav Safka wrote:
This first change introduces xml parsing support for preallocated shared file descriptor based memory backing. It allows vhost-user to be used without hugepages.
New xml elements: <memoryBacking> <source type='file|anonymous' path='/path/to/qemu/' />
I'm pretty sure I said previously that path should *not* be present in the XML, as that is a linux-ism / internal impl detail not appropriate to expose.
<access Mode='shared|private'/> <allocation mode='immediate|ondemand'/> </memoryBacking>
Okay, this is definitely interesting approach (not only because while reviewing this, I've found an old branch in my git where I've started to work on this).
Frankly, I don't know if this is a good API or not. Historically, we required Dan's ACK on XML schema :-)
It is mostly ok, but what I think is missing though is integration with the existing logic in this area. eg we have a access mode attribute on the NUMA cell: <cell id='1' cpus='4-7' memory='512000' unit='KiB' memAccess='shared'/> if this attribute is *not* specified on the NUMA cell, then the parser should be auto-filling it based on the top level <access mode> element. And of course test files to demonstrate that is working.
--- docs/schemas/domaincommon.rng | 37 +++++ src/conf/domain_conf.c | 149 ++++++++++++++++----- src/conf/domain_conf.h | 34 +++++ .../qemuxml2argv-memorybacking-set.xml | 32 +++++ .../qemuxml2argv-memorybacking-unset.xml | 32 +++++ .../qemuxml2xmlout-memorybacking-set.xml | 40 ++++++ .../qemuxml2xmlout-memorybacking-unset.xml | 40 ++++++ tests/qemuxml2xmltest.c | 3 + 8 files changed, 334 insertions(+), 33 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml
You need to update the docs too. formatdomain.html.in to be more precise.
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :|

Hi, thanks all for review Comments inside Best regards Jarek
-----Original Message----- From: Daniel P. Berrange [mailto:berrange@redhat.com] Sent: Tuesday, October 04, 2016 5:15 PM To: Michal Privoznik <mprivozn@redhat.com> Cc: Safka, JaroslavX <jaroslavx.safka@intel.com>; libvir-list@redhat.com Subject: Re: [libvirt] [PATCH 1/2] conf: Add support for preallocated fd memory
On Tue, Oct 04, 2016 at 05:07:16PM +0200, Michal Privoznik wrote:
On 29.09.2016 10:56, Jaroslav Safka wrote:
This first change introduces xml parsing support for preallocated shared file descriptor based memory backing. It allows vhost-user to be used without hugepages.
New xml elements: <memoryBacking> <source type='file|anonymous' path='/path/to/qemu/' />
I'm pretty sure I said previously that path should *not* be present in the XML, as that is a linux-ism / internal impl detail not appropriate to expose.
What way you suggest Daniel? There was two proposals in previous review from Sean to use xml or compile time parameter. Btw there is something other than Linux? ;-)) (just joke)
<access Mode='shared|private'/> <allocation mode='immediate|ondemand'/> </memoryBacking>
Okay, this is definitely interesting approach (not only because while reviewing this, I've found an old branch in my git where I've started to work on this).
Frankly, I don't know if this is a good API or not. Historically, we required Dan's ACK on XML schema :-)
It is mostly ok, but what I think is missing though is integration with the existing logic in this area.
eg we have a access mode attribute on the NUMA cell:
<cell id='1' cpus='4-7' memory='512000' unit='KiB' memAccess='shared'/>
if this attribute is *not* specified on the NUMA cell, then the parser should be auto-filling it based on the top level <access mode> element. And of course test files to demonstrate that is working.
I'm not sure if I get it. Actual code take these actions. Find (switch) for VIR_NUMA_MEM_ACCESS_SHARED in cell element. If yes then add "share" If it is VIR_NUMA_MEM_ACCESS_DEFAULT then look at the default from <access mode=.. /> And use it (add "share"). Also in reverse mode (generating xml) it will create the same xml as input xml.
--- docs/schemas/domaincommon.rng | 37 +++++ src/conf/domain_conf.c | 149 ++++++++++++++++----- src/conf/domain_conf.h | 34 +++++ .../qemuxml2argv-memorybacking-set.xml | 32 +++++ .../qemuxml2argv-memorybacking-unset.xml | 32 +++++ .../qemuxml2xmlout-memorybacking-set.xml | 40 ++++++ .../qemuxml2xmlout-memorybacking-unset.xml | 40 ++++++ tests/qemuxml2xmltest.c | 3 + 8 files changed, 334 insertions(+), 33 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memorybacking-unset.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-set.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-memorybacking-unset.xml
You need to update the docs too. formatdomain.html.in to be more precise.
Yeah thanks, I must find it and look at it :)
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :|
-------------------------------------------------------------- Intel Research and Development Ireland Limited Registered in Ireland Registered Office: Collinstown Industrial Park, Leixlip, County Kildare Registered Number: 308263 This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.

This second change introduces support for preallocated shared file descriptor based memory backing. It allows vhost-user to be used without hugepages. Used xml elements: <memoryBacking> <source type='file|anonymous' path='/path/to/qemu/' /> <access Mode='shared|private'/> <allocation mode='immediate|ondemand'/> </memoryBacking> --- src/qemu/qemu_command.c | 156 ++++++++++++++++----- src/qemu/qemu_command.h | 4 + .../qemuxml2argv-fd-memory-no-numa-topology.args | 34 +++++ .../qemuxml2argv-fd-memory-no-numa-topology.xml | 96 +++++++++++++ .../qemuxml2argv-fd-memory-numa-topology.args | 34 +++++ .../qemuxml2argv-fd-memory-numa-topology.xml | 99 +++++++++++++ tests/qemuxml2argvtest.c | 24 ++++ 7 files changed, 414 insertions(+), 33 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index f24a98b..ff661ef 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3275,15 +3275,11 @@ qemuBuildMemoryBackendStr(unsigned long long size, if (!(props = virJSONValueNewObject())) return -1; - if (pagesize) { - if (qemuGetHupageMemPath(cfg, pagesize, &mem_path) < 0) - goto cleanup; - + if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE) { *backendType = "memory-backend-file"; if (virJSONValueObjectAdd(props, - "b:prealloc", true, - "s:mem-path", mem_path, + "s:mem-path", def->mem.mem_path, NULL) < 0) goto cleanup; @@ -3299,18 +3295,61 @@ qemuBuildMemoryBackendStr(unsigned long long size, break; case VIR_NUMA_MEM_ACCESS_DEFAULT: + if (def->mem.access == VIR_DOMAIN_MEMORY_ACCESS_SHARED) { + if (virJSONValueObjectAdd(props, "b:share", true, NULL) < 0) + goto cleanup; + } + break; + case VIR_NUMA_MEM_ACCESS_LAST: break; } + + force = true; } else { - if (memAccess) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Shared memory mapping is supported " - "only with hugepages")); - goto cleanup; - } + if (pagesize) { + if (qemuGetHupageMemPath(cfg, pagesize, &mem_path) < 0) + goto cleanup; - *backendType = "memory-backend-ram"; + *backendType = "memory-backend-file"; + + if (virJSONValueObjectAdd(props, + "b:prealloc", true, + "s:mem-path", mem_path, + NULL) < 0) + goto cleanup; + + switch (memAccess) { + case VIR_NUMA_MEM_ACCESS_SHARED: + if (virJSONValueObjectAdd(props, "b:share", true, NULL) < 0) + goto cleanup; + break; + + case VIR_NUMA_MEM_ACCESS_PRIVATE: + if (virJSONValueObjectAdd(props, "b:share", false, NULL) < 0) + goto cleanup; + break; + + case VIR_NUMA_MEM_ACCESS_DEFAULT: + if (def->mem.access == VIR_DOMAIN_MEMORY_ACCESS_SHARED) { + if (virJSONValueObjectAdd(props, "b:share", true, NULL) < 0) + goto cleanup; + } + break; + + case VIR_NUMA_MEM_ACCESS_LAST: + break; + } + } else { + if (memAccess) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Shared memory mapping is supported " + "only with hugepages")); + goto cleanup; + } + + *backendType = "memory-backend-ram"; + } } if (virJSONValueObjectAdd(props, "U:size", size * 1024, NULL) < 0) @@ -7153,28 +7192,35 @@ qemuBuildMemPathStr(virQEMUDriverConfigPtr cfg, const long system_page_size = virGetSystemPageSizeKB(); char *mem_path = NULL; - /* - * No-op if hugepages were not requested. - */ - if (!def->mem.nhugepages) + if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) { + virCommandAddArgList(cmd, "-mem-prealloc", NULL); return 0; + } - /* There is one special case: if user specified "huge" - * pages of regular system pages size. - * And there is nothing to do in this case. - */ - if (def->mem.hugepages[0].size == system_page_size) - return 0; + if (def->mem.nhugepages) { - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_PATH)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("hugepage backing not supported by '%s'"), - def->emulator); - return -1; - } + /* There is one special case: if user specified "huge" + * pages of regular system pages size. + * And there is nothing to do in this case. + */ + if (def->mem.hugepages[0].size == system_page_size) + return 0; - if (qemuGetHupageMemPath(cfg, def->mem.hugepages[0].size, &mem_path) < 0) - return -1; + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_PATH)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("hugepage backing not supported by '%s'"), + def->emulator); + return -1; + } + + if (qemuGetHupageMemPath(cfg, def->mem.hugepages[0].size, &mem_path) < 0) + return -1; + } else { + /* + * No-op if hugepages or immediate allocation were not requested. + */ + return 0; + } virCommandAddArgList(cmd, "-mem-prealloc", "-mem-path", mem_path, NULL); VIR_FREE(mem_path); @@ -7210,8 +7256,9 @@ qemuBuildMemCommandLine(virCommandPtr cmd, * Add '-mem-path' (and '-mem-prealloc') parameter here only if * there is no numa node specified. */ - if (!virDomainNumaGetNodeCount(def->numa) && - qemuBuildMemPathStr(cfg, def, qemuCaps, cmd) < 0) + if ((!virDomainNumaGetNodeCount(def->numa) + || def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) + && qemuBuildMemPathStr(cfg, def, qemuCaps, cmd) < 0) return -1; if (def->mem.locked && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_REALTIME_MLOCK)) { @@ -9411,6 +9458,10 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, qemuBuildNumaArgStr(cfg, def, cmd, qemuCaps, nodeset) < 0) goto error; + if (!virDomainNumaGetNodeCount(def->numa) && + qemuBuildMemoryBackingCommandLine(def, cmd, qemuCaps) < 0) + goto error; + if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, qemuCaps, nodeset) < 0) goto error; @@ -9801,6 +9852,45 @@ qemuBuildChrDeviceStr(char **deviceStr, return ret; } +int +qemuBuildMemoryBackingCommandLine(const virDomainDef *def, + virCommandPtr cmd, + virQEMUCapsPtr qemuCaps) +{ + int ret = -1; + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *alias = "ram"; + + if (def->mem.source != VIR_DOMAIN_MEMORY_SOURCE_FILE) { + ret = 0; + goto cleanup; + } + /* numa is disabled and mem source is file */ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("File memory mapping is not supported " + "with this QEMU")); + goto cleanup; + } + + virCommandAddArg(cmd, "-object"); + virBufferAsprintf(&buf, "memory-backend-file,id=%s,mem-path=%s,", alias, def->mem.mem_path); + + if (def->mem.access == VIR_DOMAIN_MEMORY_ACCESS_SHARED) + virBufferAsprintf(&buf, "%s", "share=yes,"); + + virBufferAsprintf(&buf, "size=%llu", virDomainDefGetMemoryInitial(def) / 1024); + virCommandAddArgBuffer(cmd, &buf); + + virCommandAddArg(cmd, "-numa"); + virCommandAddArgFormat(cmd, "node,memdev=%s", alias); + + ret = 0; + cleanup: + + virBufferFreeAndReset(&buf); + return ret; +} virJSONValuePtr diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 2f2a6ff..d5cc0dd 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -182,6 +182,10 @@ bool qemuCheckCCWS390AddressSupport(const virDomainDef *def, virDomainDeviceInfo info, virQEMUCapsPtr qemuCaps, const char *devicename); +int +qemuBuildMemoryBackingCommandLine(const virDomainDef *def, + virCommandPtr cmd, + virQEMUCapsPtr qemuCaps); virJSONValuePtr qemuBuildHotpluggableCPUProps(const virDomainVcpuDef *vcpu) ATTRIBUTE_NONNULL(1); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.args b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.args new file mode 100644 index 0000000..952a699 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.args @@ -0,0 +1,34 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name instance-00000092 \ +-S \ +-M pc-i440fx-wily \ +-cpu host \ +-m 14336 \ +-mem-prealloc \ +-smp 8,sockets=8,cores=1,threads=1 \ +-object memory-backend-file,id=ram,mem-path=/var/lib/libvirt/qemu/,share=yes,\ +size=14336 \ +-numa node,memdev=ram \ +-uuid 126f2720-6f8e-45ab-a886-ec9277079a67 \ +-smbios 'type=1,manufacturer=OpenStack Foundation,product=OpenStack Nova,\ +version=13.0.0,serial=0640ddd5-36c9-e211-a2f6-001e6789a0f1,\ +uuid=126f2720-6f8e-45ab-a886-ec9277079a67,family=Virtual Machine' \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-instance-00000092/monitor.sock,server,nowait \ +-rtc base=utc,driftfix=slew \ +-no-kvm-pit-reinjection \ +-boot c \ +-usb \ +-drive file=/var/lib/nova/instances/126f2720-6f8e-45ab-a886-ec9277079a67/disk,\ +format=qcow2,if=none,id=drive-virtio-disk0,cache=none \ +-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-vga cirrus \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.xml b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.xml new file mode 100644 index 0000000..b25628c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-no-numa-topology.xml @@ -0,0 +1,96 @@ +<domain type='kvm' id='56'> + <name>instance-00000092</name> + <uuid>126f2720-6f8e-45ab-a886-ec9277079a67</uuid> + <metadata> + <nova:instance xmlns:nova="http://openstack.org/xmlns/libvirt/nova/1.0"> + <nova:package version="13.0.0"/> + <nova:name>emma</nova:name> + <nova:creationTime>2016-09-16 15:51:06</nova:creationTime> + <nova:flavor name="devstack"> + <nova:memory>14336</nova:memory> + <nova:disk>30</nova:disk> + <nova:swap>0</nova:swap> + <nova:ephemeral>0</nova:ephemeral> + <nova:vcpus>8</nova:vcpus> + </nova:flavor> + <nova:owner> + <nova:user uuid="ff95838725294b1896e887d4caee5e1a">tester</nova:user> + <nova:project uuid="f04e5e9722e441ae90bcc7f12722a0ac">test</nova:project> + </nova:owner> + <nova:root type="image" uuid="37ec79a5-9eb2-4df5-beee-a6942657d828"/> + </nova:instance> + </metadata> + <memory unit='KiB'>14680064</memory> + <currentMemory unit='KiB'>14680064</currentMemory> + <memoryBacking> + <source type='file' path='/var/lib/libvirt/qemu/'/> + <access mode='shared'/> + <allocation mode='immediate'/> + </memoryBacking> + <vcpu placement='static'>8</vcpu> + <cputune> + <shares>8192</shares> + </cputune> + <resource> + <partition>/machine</partition> + </resource> + <sysinfo type='smbios'> + <system> + <entry name='manufacturer'>OpenStack Foundation</entry> + <entry name='product'>OpenStack Nova</entry> + <entry name='version'>13.0.0</entry> + <entry name='serial'>0640ddd5-36c9-e211-a2f6-001e6789a0f1</entry> + <entry name='uuid'>126f2720-6f8e-45ab-a886-ec9277079a67</entry> + <entry name='family'>Virtual Machine</entry> + </system> + </sysinfo> + <os> + <type arch='x86_64' machine='pc-i440fx-wily'>hvm</type> + <boot dev='hd'/> + <smbios mode='sysinfo'/> + </os> + <features> + <acpi/> + <apic/> + </features> + <cpu mode='host-passthrough'> + <topology sockets='8' cores='1' threads='1'/> + </cpu> + <clock offset='utc'> + <timer name='pit' tickpolicy='delay'/> + <timer name='rtc' tickpolicy='catchup'/> + <timer name='hpet' present='no'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/var/lib/nova/instances/126f2720-6f8e-45ab-a886-ec9277079a67/disk'/> + <backingStore type='file' index='1'> + <format type='raw'/> + <source file='/var/lib/nova/instances/_base/7205b893db62340da7d5246a23b66a52ccef9bd1'/> + <backingStore/> + </backingStore> + <target dev='vda' bus='virtio'/> + <alias name='virtio-disk0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <video> + <model type='cirrus' vram='16384' heads='1'/> + <alias name='video0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <stats period='10'/> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.args b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.args new file mode 100644 index 0000000..55b739f --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.args @@ -0,0 +1,34 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name instance-00000092 \ +-S \ +-M pc-i440fx-wily \ +-cpu host \ +-m 14336 \ +-mem-prealloc \ +-smp 8,sockets=1,cores=8,threads=1 \ +-object memory-backend-file,id=ram-node0,mem-path=/var/lib/libvirt/qemu/,\ +share=yes,size=15032385536 \ +-numa node,nodeid=0,cpus=0-7,memdev=ram-node0 \ +-uuid 126f2720-6f8e-45ab-a886-ec9277079a67 \ +-smbios 'type=1,manufacturer=OpenStack Foundation,product=OpenStack Nova,\ +version=13.0.0,serial=0640ddd5-36c9-e211-a2f6-001e6789a0f1,\ +uuid=126f2720-6f8e-45ab-a886-ec9277079a67,family=Virtual Machine' \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-instance-00000092/monitor.sock,server,nowait \ +-rtc base=utc,driftfix=slew \ +-no-kvm-pit-reinjection \ +-boot c \ +-usb \ +-drive file=/var/lib/nova/instances/126f2720-6f8e-45ab-a886-ec9277079a67/disk,\ +format=qcow2,if=none,id=drive-virtio-disk0,cache=none \ +-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-vga cirrus \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.xml b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.xml new file mode 100644 index 0000000..1f74601 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-fd-memory-numa-topology.xml @@ -0,0 +1,99 @@ + <domain type='kvm' id='56'> + <name>instance-00000092</name> + <uuid>126f2720-6f8e-45ab-a886-ec9277079a67</uuid> + <metadata> + <nova:instance xmlns:nova="http://openstack.org/xmlns/libvirt/nova/1.0"> + <nova:package version="13.0.0"/> + <nova:name>emma</nova:name> + <nova:creationTime>2016-09-16 15:51:06</nova:creationTime> + <nova:flavor name="devstack"> + <nova:memory>14336</nova:memory> + <nova:disk>30</nova:disk> + <nova:swap>0</nova:swap> + <nova:ephemeral>0</nova:ephemeral> + <nova:vcpus>8</nova:vcpus> + </nova:flavor> + <nova:owner> + <nova:user uuid="ff95838725294b1896e887d4caee5e1a">tester</nova:user> + <nova:project uuid="f04e5e9722e441ae90bcc7f12722a0ac">test</nova:project> + </nova:owner> + <nova:root type="image" uuid="37ec79a5-9eb2-4df5-beee-a6942657d828"/> + </nova:instance> + </metadata> + <memory unit='KiB'>14680064</memory> + <currentMemory unit='KiB'>14680064</currentMemory> + <memoryBacking> + <source type='file' path='/var/lib/libvirt/qemu/'/> + <access mode='shared'/> + <allocation mode='immediate'/> + </memoryBacking> + <vcpu placement='static'>8</vcpu> + <cputune> + <shares>8192</shares> + </cputune> + <resource> + <partition>/machine</partition> + </resource> + <sysinfo type='smbios'> + <system> + <entry name='manufacturer'>OpenStack Foundation</entry> + <entry name='product'>OpenStack Nova</entry> + <entry name='version'>13.0.0</entry> + <entry name='serial'>0640ddd5-36c9-e211-a2f6-001e6789a0f1</entry> + <entry name='uuid'>126f2720-6f8e-45ab-a886-ec9277079a67</entry> + <entry name='family'>Virtual Machine</entry> + </system> + </sysinfo> + <os> + <type arch='x86_64' machine='pc-i440fx-wily'>hvm</type> + <boot dev='hd'/> + <smbios mode='sysinfo'/> + </os> + <features> + <acpi/> + <apic/> + </features> + <cpu mode='host-passthrough'> + <topology sockets='1' cores='8' threads='1'/> + <numa> + <cell id='0' cpus='0-7' memory='14680064' unit='KiB'/> + </numa> + </cpu> + <clock offset='utc'> + <timer name='pit' tickpolicy='delay'/> + <timer name='rtc' tickpolicy='catchup'/> + <timer name='hpet' present='no'/> + </clock> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/var/lib/nova/instances/126f2720-6f8e-45ab-a886-ec9277079a67/disk'/> + <backingStore type='file' index='1'> + <format type='raw'/> + <source file='/var/lib/nova/instances/_base/7205b893db62340da7d5246a23b66a52ccef9bd1'/> + <backingStore/> + </backingStore> + <target dev='vda' bus='virtio'/> + <alias name='virtio-disk0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <video> + <model type='cirrus' vram='16384' heads='1'/> + <alias name='video0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <stats period='10'/> + <alias name='balloon0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> + </domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 0af71a1..9564e14 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2160,6 +2160,30 @@ mymain(void) DO_TEST("cpu-hotplug-startup", QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS); + DO_TEST("fd-memory-numa-topology", QEMU_CAPS_RTC, QEMU_CAPS_NO_KVM_PIT, + QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_ICH9_USB_EHCI1, QEMU_CAPS_PCI_MULTIFUNCTION, + QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV_SPICEVMC, + QEMU_CAPS_VGA_QXL, + QEMU_CAPS_HDA_DUPLEX, QEMU_CAPS_USB_REDIR, + QEMU_CAPS_DEVICE_PC_DIMM, + QEMU_CAPS_MEM_PATH, QEMU_CAPS_OBJECT_MEMORY_FILE, + QEMU_CAPS_KVM, QEMU_CAPS_SMBIOS_TYPE, + QEMU_CAPS_VNC_WEBSOCKET, QEMU_CAPS_VNC); + + DO_TEST("fd-memory-no-numa-topology", QEMU_CAPS_RTC, QEMU_CAPS_NO_KVM_PIT, + QEMU_CAPS_PIIX_DISABLE_S3, QEMU_CAPS_PIIX_DISABLE_S4, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_ICH9_USB_EHCI1, QEMU_CAPS_PCI_MULTIFUNCTION, + QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV_SPICEVMC, + QEMU_CAPS_VGA_QXL, + QEMU_CAPS_HDA_DUPLEX, QEMU_CAPS_USB_REDIR, + QEMU_CAPS_DEVICE_PC_DIMM, + QEMU_CAPS_MEM_PATH, QEMU_CAPS_OBJECT_MEMORY_FILE, + QEMU_CAPS_KVM, QEMU_CAPS_SMBIOS_TYPE, + QEMU_CAPS_VNC_WEBSOCKET, QEMU_CAPS_VNC); + qemuTestDriverFree(&driver); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -- 2.5.5 -------------------------------------------------------------- Intel Research and Development Ireland Limited Registered in Ireland Registered Office: Collinstown Industrial Park, Leixlip, County Kildare Registered Number: 308263 This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
participants (4)
-
Daniel P. Berrange
-
Jaroslav Safka
-
Michal Privoznik
-
Safka, JaroslavX