xml: <devices> <memballoon model='virtio' free-page-reporting='on'/> </devices> qemu: qemu -device virtio-balloon-pci,...,free-page-reporting=on This kernel feature allows for more stable and resource friendly systems. Signed-off-by: Nico Pache <npache@xxxxxxxxxx> --- docs/formatdomain.rst | 6 ++++++ docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 21 +++++++++++++++++++ src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 4 +++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 5 +++++ src/qemu/qemu_validate.c | 7 +++++++ .../caps_5.1.0.x86_64.xml | 1 + .../caps_5.2.0.x86_64.xml | 1 + 10 files changed, 51 insertions(+), 1 deletion(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index f3cf9e1fb3..f4c7765f5f 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -6755,6 +6755,12 @@ Example: manually added device with static PCI slot 2 requested release some memory at the last moment before a guest's process get killed by Out of Memory killer. :since:`Since 1.3.1, QEMU and KVM only` +``free-page-reporting`` + The optional ``free-page-reporting`` attribute allows to enable/disable + ("on"/"off", respectively) the ability of the QEMU virtio memory balloon to + return unused pages back to the hypervisor to be used by other guests or + processes. :since:`Since 5.1, QEMU and KVM only` + ``period`` The optional ``period`` allows the QEMU virtio memory balloon driver to provide statistics through the ``virsh dommemstat [domain]`` diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 4b7e460148..4c32b3555f 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4539,6 +4539,11 @@ <ref name="virOnOff"/> </attribute> </optional> + <optional> + <attribute name="free-page-reporting"> + <ref name="virOnOff"/> + </attribute> + </optional> <interleave> <optional> <ref name="alias"/> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b80d7c7c6c..f4b8e8d8c3 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -15384,6 +15384,7 @@ virDomainMemballoonDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_XPATH_NODE_AUTORESTORE(ctxt) unsigned int period = 0; g_autofree char *model = NULL; + g_autofree char *freepage_reporting = NULL; g_autofree char *deflate = NULL; if (VIR_ALLOC(def) < 0) @@ -15409,6 +15410,13 @@ virDomainMemballoonDefParseXML(virDomainXMLOptionPtr xmlopt, goto error; } + if ((freepage_reporting = virXMLPropString(node, "free-page-reporting")) && + (def->free_page_reporting = virTristateSwitchTypeFromString(freepage_reporting)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid free-page-reporting attribute value '%s'"), freepage_reporting); + goto error; + } + ctxt->node = node; if (virXPathUInt("string(./stats/@period)", ctxt, &period) < -1) { virReportError(VIR_ERR_XML_ERROR, "%s", @@ -23630,6 +23638,15 @@ virDomainMemballoonDefCheckABIStability(virDomainMemballoonDefPtr src, return false; } + if (src->free_page_reporting != dst->free_page_reporting) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target balloon free-page-reporting attribute value " + "'%s' does not match source '%s'"), + virTristateSwitchTypeToString(dst->free_page_reporting), + virTristateSwitchTypeToString(src->free_page_reporting)); + return false; + } + if (src->virtio && dst->virtio && !virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio)) return false; @@ -27737,6 +27754,10 @@ virDomainMemballoonDefFormat(virBufferPtr buf, virBufferAsprintf(&attrBuf, " autodeflate='%s'", virTristateSwitchTypeToString(def->autodeflate)); + if (def->free_page_reporting != VIR_TRISTATE_SWITCH_ABSENT) + virBufferAsprintf(&attrBuf, " free-page-reporting='%s'", + virTristateSwitchTypeToString(def->free_page_reporting)); + if (def->period) virBufferAsprintf(&childrenBuf, "<stats period='%i'/>\n", def->period); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9a44315519..f5f8baf32c 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1790,6 +1790,7 @@ struct _virDomainMemballoonDef { virDomainDeviceInfo info; int period; /* seconds between collections */ int autodeflate; /* enum virTristateSwitch */ + int free_page_reporting; /* enum virTristateSwitch */ virDomainVirtioOptionsPtr virtio; }; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5dcfcd574d..88a2c8aacb 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -600,7 +600,8 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 380 */ "usb-host.hostdevice", - ); + "virtio-balloon-pci.free-page-reporting", + ); typedef struct _virQEMUCapsMachineType virQEMUCapsMachineType; @@ -1344,6 +1345,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsVirtioBalloon[] { "iommu_platform", QEMU_CAPS_VIRTIO_PCI_IOMMU_PLATFORM, NULL }, { "ats", QEMU_CAPS_VIRTIO_PCI_ATS, NULL }, { "packed", QEMU_CAPS_VIRTIO_PACKED_QUEUES, NULL }, + { "free-page-reporting", QEMU_CAPS_VIRTIO_BALLOON_FREE_PAGE_REPORTING, NULL }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 98d70cfa0e..6f39bf156f 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -580,6 +580,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 380 */ QEMU_CAPS_USB_HOST_HOSTDEVICE, /* -device usb-host.hostdevice */ + QEMU_CAPS_VIRTIO_BALLOON_FREE_PAGE_REPORTING, /*virtio balloon free-page-reporting */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index e9ba81d82f..f80efaf026 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3830,6 +3830,11 @@ qemuBuildMemballoonCommandLine(virCommandPtr cmd, virTristateSwitchTypeToString(def->memballoon->autodeflate)); } + if (def->memballoon->free_page_reporting != VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(&buf, ",free-page-reporting=%s", + virTristateSwitchTypeToString(def->memballoon->free_page_reporting)); + } + qemuBuildVirtioOptionsStr(&buf, def->memballoon->virtio); if (qemuCommandAddExtDevice(cmd, &def->memballoon->info) < 0) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index a212605579..cfeb1e67c4 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3926,6 +3926,13 @@ qemuValidateDomainDeviceDefMemballoon(const virDomainMemballoonDef *memballoon, return -1; } + if (memballoon->free_page_reporting != VIR_TRISTATE_SWITCH_ABSENT && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BALLOON_FREE_PAGE_REPORTING)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("free-page-reporting is not supported by this QEMU binary")); + return -1; + } + if (qemuValidateDomainVirtioOptions(memballoon->virtio, qemuCaps) < 0) return -1; diff --git a/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml index 987beb965e..1f1615b94b 100644 --- a/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.1.0.x86_64.xml @@ -243,6 +243,7 @@ <flag name='numa.hmat'/> <flag name='blockdev-hostdev-scsi'/> <flag name='usb-host.hostdevice'/> + <flag name='virtio-balloon-pci.free-page-reporting'/> <version>5001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml index 3ee678ef8f..82f9051101 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml @@ -243,6 +243,7 @@ <flag name='numa.hmat'/> <flag name='blockdev-hostdev-scsi'/> <flag name='usb-host.hostdevice'/> + <flag name='virtio-balloon-pci.free-page-reporting'/> <version>5001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> -- 2.18.4