diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index fe80beebe0..4af0b82569 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2000,6 +2000,7 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off. 128 + ... @@ -2230,6 +2231,11 @@ are: tb-cache The size of translation block cache size an integer (a multiple of MiB) :since:`8.0.0` =========== ============================================== =================================================== ============== +``async-teardown`` + Depending on the ``enabled`` attribute (values ``yes``, ``no``) enable or + disable QEMU asynchronous teardown to improve memory reclaiming on a guest. + :since:`Since 9.6.0` (QEMU only) + Time keeping ------------ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 4121b6a054..5ac5c0b771 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -181,6 +181,7 @@ VIR_ENUM_IMPL(virDomainFeature, "sbbc", "ibs", "tcg", + "async-teardown", ); VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, @@ -16689,6 +16690,20 @@ virDomainFeaturesDefParse(virDomainDef *def, return -1; break; + case VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN: { + virTristateBool enabled; + + if (virXMLPropTristateBool(nodes[i], "enabled", + VIR_XML_PROP_NONE, &enabled) < 0) + return -1; + + if (enabled == VIR_TRISTATE_BOOL_ABSENT) + enabled = VIR_TRISTATE_BOOL_YES; + + def->features[val] = enabled; + break; + } + case VIR_DOMAIN_FEATURE_LAST: break; } @@ -20628,6 +20643,7 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src, case VIR_DOMAIN_FEATURE_MSRS: case VIR_DOMAIN_FEATURE_TCG: + case VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN: case VIR_DOMAIN_FEATURE_LAST: break; } @@ -27340,6 +27356,12 @@ virDomainDefFormatFeatures(virBuffer *buf, virDomainFeatureTCGFormat(&childBuf, def); break; + case VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN: + if (def->features[i] != VIR_TRISTATE_SWITCH_ABSENT) + virBufferAsprintf(&childBuf, "\n", + virTristateBoolTypeToString(def->features[i])); + break; + case VIR_DOMAIN_FEATURE_LAST: break; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index cddaa3824d..c857ba556f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2170,6 +2170,7 @@ typedef enum { VIR_DOMAIN_FEATURE_SBBC, VIR_DOMAIN_FEATURE_IBS, VIR_DOMAIN_FEATURE_TCG, + VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN, VIR_DOMAIN_FEATURE_LAST } virDomainFeature; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index fcf9e00600..c2f56b0490 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6660,6 +6660,15 @@ + + + + + + + + + diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 09fa3dad79..ad224571f3 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -10177,6 +10177,25 @@ qemuBuildCryptoCommandLine(virCommand *cmd, } +static int +qemuBuildAsyncTeardownCommandLine(virCommand *cmd, + const virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + g_autofree char *async = NULL; + virTristateBool enabled = def->features[VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN]; + + if (enabled != VIR_TRISTATE_BOOL_ABSENT && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_RUN_WITH_ASYNC_TEARDOWN)) { + async = g_strdup_printf("async-teardown=%s", + virTristateSwitchTypeToString(enabled)); + virCommandAddArgList(cmd, "-run-with", async, NULL); + } + + return 0; +} + + typedef enum { QEMU_COMMAND_DEPRECATION_BEHAVIOR_NONE = 0, QEMU_COMMAND_DEPRECATION_BEHAVIOR_OMIT, @@ -10532,6 +10551,9 @@ qemuBuildCommandLine(virDomainObj *vm, if (qemuBuildCryptoCommandLine(cmd, def, qemuCaps) < 0) return NULL; + if (qemuBuildAsyncTeardownCommandLine(cmd, def, qemuCaps) < 0) + return NULL; + if (cfg->logTimestamp) virCommandAddArgList(cmd, "-msg", "timestamp=on", NULL); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index a53729d349..7e09e2c52f 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -219,6 +219,15 @@ qemuValidateDomainDefFeatures(const virDomainDef *def, } break; + case VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN: + if (def->features[i] == VIR_TRISTATE_BOOL_YES && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_RUN_WITH_ASYNC_TEARDOWN)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("asynchronous teardown is not available with this QEMU binary")); + return -1; + } + break; + case VIR_DOMAIN_FEATURE_SMM: case VIR_DOMAIN_FEATURE_KVM: case VIR_DOMAIN_FEATURE_XEN: diff --git a/tests/qemuxml2argvdata/async-teardown.x86_64-latest.args b/tests/qemuxml2argvdata/async-teardown.x86_64-latest.args new file mode 100644 index 0000000000..455382f1f0 --- /dev/null +++ b/tests/qemuxml2argvdata/async-teardown.x86_64-latest.args @@ -0,0 +1,37 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \ +-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-run-with async-teardown=on \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/async-teardown.xml b/tests/qemuxml2argvdata/async-teardown.xml new file mode 100644 index 0000000000..70c1eccc55 --- /dev/null +++ b/tests/qemuxml2argvdata/async-teardown.xml @@ -0,0 +1,31 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + + + + /usr/bin/qemu-system-x86_64 + + + +
+ + + + + + + + diff --git a/tests/qemuxml2argvdata/s390-async-teardown-disabled.s390x-6.0.0.args b/tests/qemuxml2argvdata/s390-async-teardown-disabled.s390x-6.0.0.args new file mode 100644 index 0000000000..57690530a2 --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown-disabled.s390x-6.0.0.args @@ -0,0 +1,35 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-s390x \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine s390-ccw-virtio-6.0,usb=off,dump-guest-core=off,memory-backend=s390.ram \ +-accel tcg \ +-cpu qemu \ +-m size=262144k \ +-object '{"qom-type":"memory-backend-ram","id":"s390.ram","size":268435456}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 9aa4b45c-b9dd-45ef-91fe-862b27b4231f \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device virtio-serial-ccw,id=virtio-serial0,devno=fe.0.0000 \ +-chardev pty,id=charconsole0 \ +-device virtconsole,chardev=charconsole0,id=console0 \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0001 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/s390-async-teardown-disabled.s390x-latest.args b/tests/qemuxml2argvdata/s390-async-teardown-disabled.s390x-latest.args new file mode 100644 index 0000000000..96b18b83ce --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown-disabled.s390x-latest.args @@ -0,0 +1,36 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-s390x \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine s390-ccw-virtio,usb=off,dump-guest-core=off,memory-backend=s390.ram \ +-accel tcg \ +-cpu qemu \ +-m size=262144k \ +-object '{"qom-type":"memory-backend-ram","id":"s390.ram","size":268435456}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 9aa4b45c-b9dd-45ef-91fe-862b27b4231f \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"virtio-serial-ccw","id":"virtio-serial0","devno":"fe.0.0000"}' \ +-chardev pty,id=charconsole0 \ +-device '{"driver":"virtconsole","chardev":"charconsole0","id":"console0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-ccw","id":"balloon0","devno":"fe.0.0001"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-run-with async-teardown=off \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/s390-async-teardown-disabled.xml b/tests/qemuxml2argvdata/s390-async-teardown-disabled.xml new file mode 100644 index 0000000000..3939be0006 --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown-disabled.xml @@ -0,0 +1,24 @@ + + QEMUGuest1 + 9aa4b45c-b9dd-45ef-91fe-862b27b4231f + 262144 + 262144 + + hvm + + + destroy + restart + destroy + + + + + /usr/bin/qemu-system-s390x + + + + + + + diff --git a/tests/qemuxml2argvdata/s390-async-teardown-no-attrib.s390x-latest.args b/tests/qemuxml2argvdata/s390-async-teardown-no-attrib.s390x-latest.args new file mode 100644 index 0000000000..cc7866499f --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown-no-attrib.s390x-latest.args @@ -0,0 +1,36 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-s390x \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine s390-ccw-virtio,usb=off,dump-guest-core=off,memory-backend=s390.ram \ +-accel tcg \ +-cpu qemu \ +-m size=262144k \ +-object '{"qom-type":"memory-backend-ram","id":"s390.ram","size":268435456}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 9aa4b45c-b9dd-45ef-91fe-862b27b4231f \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"virtio-serial-ccw","id":"virtio-serial0","devno":"fe.0.0000"}' \ +-chardev pty,id=charconsole0 \ +-device '{"driver":"virtconsole","chardev":"charconsole0","id":"console0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-ccw","id":"balloon0","devno":"fe.0.0001"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-run-with async-teardown=on \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/s390-async-teardown-no-attrib.xml b/tests/qemuxml2argvdata/s390-async-teardown-no-attrib.xml new file mode 100644 index 0000000000..e069cd41ed --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown-no-attrib.xml @@ -0,0 +1,24 @@ + + QEMUGuest1 + 9aa4b45c-b9dd-45ef-91fe-862b27b4231f + 262144 + 262144 + + hvm + + + destroy + restart + destroy + + + + + /usr/bin/qemu-system-s390x + + + + + + + diff --git a/tests/qemuxml2argvdata/s390-async-teardown.s390x-6.0.0.err b/tests/qemuxml2argvdata/s390-async-teardown.s390x-6.0.0.err new file mode 100644 index 0000000000..aa9a4739cb --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown.s390x-6.0.0.err @@ -0,0 +1 @@ +unsupported configuration: asynchronous teardown is not available with this QEMU binary diff --git a/tests/qemuxml2argvdata/s390-async-teardown.s390x-latest.args b/tests/qemuxml2argvdata/s390-async-teardown.s390x-latest.args new file mode 100644 index 0000000000..cc7866499f --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown.s390x-latest.args @@ -0,0 +1,36 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-s390x \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine s390-ccw-virtio,usb=off,dump-guest-core=off,memory-backend=s390.ram \ +-accel tcg \ +-cpu qemu \ +-m size=262144k \ +-object '{"qom-type":"memory-backend-ram","id":"s390.ram","size":268435456}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid 9aa4b45c-b9dd-45ef-91fe-862b27b4231f \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"virtio-serial-ccw","id":"virtio-serial0","devno":"fe.0.0000"}' \ +-chardev pty,id=charconsole0 \ +-device '{"driver":"virtconsole","chardev":"charconsole0","id":"console0"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-ccw","id":"balloon0","devno":"fe.0.0001"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-run-with async-teardown=on \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/s390-async-teardown.xml b/tests/qemuxml2argvdata/s390-async-teardown.xml new file mode 100644 index 0000000000..3291b1ada3 --- /dev/null +++ b/tests/qemuxml2argvdata/s390-async-teardown.xml @@ -0,0 +1,24 @@ + + QEMUGuest1 + 9aa4b45c-b9dd-45ef-91fe-862b27b4231f + 262144 + 262144 + + hvm + + + destroy + restart + destroy + + + + + /usr/bin/qemu-system-s390x + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 79148a3ec3..534eb9e699 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2701,6 +2701,13 @@ mymain(void) DO_TEST_CAPS_LATEST("crypto-builtin"); + DO_TEST_CAPS_LATEST("async-teardown"); + DO_TEST_CAPS_ARCH_LATEST("s390-async-teardown", "s390x"); + DO_TEST_CAPS_ARCH_LATEST("s390-async-teardown-no-attrib", "s390x"); + DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("s390-async-teardown", "s390x", "6.0.0"); + DO_TEST_CAPS_ARCH_LATEST("s390-async-teardown-disabled", "s390x"); + DO_TEST_CAPS_ARCH_VER("s390-async-teardown-disabled", "s390x", "6.0.0"); + qemuTestDriverFree(&driver); virFileWrapperClearPrefixes(); diff --git a/tests/qemuxml2xmloutdata/async-teardown.x86_64-latest.xml b/tests/qemuxml2xmloutdata/async-teardown.x86_64-latest.xml new file mode 100644 index 0000000000..e98308a9b1 --- /dev/null +++ b/tests/qemuxml2xmloutdata/async-teardown.x86_64-latest.xml @@ -0,0 +1,44 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + + + + qemu64 + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + +
+ + +
+ + + +
+ + + + +