[PATCH v1 0/6] support mode option for dirtyrate calculation

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> v1: This patchset introduce mode option as the supplement of qemuDomainStartDirtyRateCalc api, add calc_mode for dirtyrate statistics correspondingly. Qemu add mode parameter for calc-dirty-rate command since >= 6.2.0, either of these three mode "page-sampling, dirty-bitmap, dirty-ring" can be specified when calculating dirty page rate. Page sampling is the original mode and used as default mode. Dirty bitmap mode use kvm log sync api to fetch the dirty-bitmap and count the increased 1 bits number during measurement, thus, calculate the dirty page rate. Dirty ring mode use the dirty-ring mechanism implemented in Qemu which can count the increased dirty page on virtual cpu granularity, thus, calculate the per-vcpu dirty page rate. These three calculation mode can be used in different scenarios, and the dirty-bitmap, dirty-ring mode may be more accurate to a certain degree. So maybe it's time to support the mode option for dirtyrate calculation. This series make main modifications as the following: 1. introduce QEMU_CAPS_CALC_DIRTY_RATE capability to probe calc-dirty-rate command in case of failure since it just introduced since >= 5.2.0 2. introduce QEMU_CAPS_DIRTYRATE_MODE capability to probe mode option of calc-dirty-rate command in case of failure, same as 1. 3. implement mode option support for dirtyrate calculation. Please review, thanks ! Best Regards ! Hyman Huang(黄勇) (6): qemu_capabilities: Introduce QEMU_CAPS_CALC_DIRTY_RATE capability qemu_driver: Probe capability before calculating dirty page rate qemu_capabilities: Introduce QEMU_CAPS_DIRTYRATE_MODE capability qemu_driver: Add mode option for qemuDomainStartDirtyRateCalc virsh: Extend domdirtyrate-calc virsh api qemu_driver: Add calc_mode for dirtyrate statistics docs/manpages/virsh.rst | 7 +- include/libvirt/libvirt-domain.h | 13 ++++ src/libvirt-domain.c | 17 ++++- src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_driver.c | 59 ++++++++++++++++- src/qemu/qemu_monitor.c | 5 +- src/qemu/qemu_monitor.h | 20 +++++- src/qemu/qemu_monitor_json.c | 78 +++++++++++++++++++++-- src/qemu/qemu_monitor_json.h | 3 +- tests/qemucapabilitiesdata/caps_5.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml | 2 + tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 2 + tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml | 2 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 2 + tools/virsh-domain.c | 28 +++++++- 25 files changed, 239 insertions(+), 15 deletions(-) -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> calc-dirty-rate command was introduced since qemu >=5.2.0. Introduce QEMU_CAPS_CALC_DIRTY_RATE capability definition. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_5.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 1 + 16 files changed, 17 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 461a818..de08e81 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -657,6 +657,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 420 */ "device.json+hotplug", /* QEMU_CAPS_DEVICE_JSON */ + "calc-dirty-rate", /* QEMU_CAPS_CALC_DIRTY_RATE */ ); @@ -1187,6 +1188,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = { { "set-action", QEMU_CAPS_SET_ACTION }, { "query-dirty-rate", QEMU_CAPS_QUERY_DIRTY_RATE }, { "sev-inject-launch-secret", QEMU_CAPS_SEV_INJECT_LAUNCH_SECRET }, + { "calc-dirty-rate", QEMU_CAPS_CALC_DIRTY_RATE }, }; struct virQEMUCapsStringFlags virQEMUCapsMigration[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 7d42e3a..598cef9 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -636,6 +636,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 420 */ QEMU_CAPS_DEVICE_JSON, /* -device accepts JSON (and works with hot-unplug) */ + QEMU_CAPS_CALC_DIRTY_RATE, /* accepts calc-dirty-rate */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_5.2.0.aarch64.xml index e809b95..9f14d59 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.aarch64.xml @@ -183,6 +183,7 @@ <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> <flag name='query-dirty-rate'/> + <flag name='calc-dirty-rate'/> <version>5002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_5.2.0.ppc64.xml index 0cbbffe..e050514 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.ppc64.xml @@ -189,6 +189,7 @@ <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> <flag name='query-dirty-rate'/> + <flag name='calc-dirty-rate'/> <version>5002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.riscv64.xml b/tests/qemucapabilitiesdata/caps_5.2.0.riscv64.xml index 13a6967..4b123d4 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.riscv64.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.riscv64.xml @@ -173,6 +173,7 @@ <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> <flag name='query-dirty-rate'/> + <flag name='calc-dirty-rate'/> <version>5002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>0</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.s390x.xml b/tests/qemucapabilitiesdata/caps_5.2.0.s390x.xml index 518bb7a..bc3c3c3 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.s390x.xml @@ -140,6 +140,7 @@ <flag name='query-display-options'/> <flag name='virtio-blk.queue-size'/> <flag name='query-dirty-rate'/> + <flag name='calc-dirty-rate'/> <version>5002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>39100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml index 64e7bc2..70ad14f 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml @@ -225,6 +225,7 @@ <flag name='virtio-mem-pci'/> <flag name='piix4.acpi-root-pci-hotplug'/> <flag name='query-dirty-rate'/> + <flag name='calc-dirty-rate'/> <version>5002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.0.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_6.0.0.aarch64.xml index 743f7d9..9d501f2 100644 --- a/tests/qemucapabilitiesdata/caps_6.0.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_6.0.0.aarch64.xml @@ -191,6 +191,7 @@ <flag name='set-action'/> <flag name='virtio-blk.queue-size'/> <flag name='query-dirty-rate'/> + <flag name='calc-dirty-rate'/> <version>6000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.0.0.s390x.xml b/tests/qemucapabilitiesdata/caps_6.0.0.s390x.xml index b034ffd..02b24f5 100644 --- a/tests/qemucapabilitiesdata/caps_6.0.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_6.0.0.s390x.xml @@ -148,6 +148,7 @@ <flag name='set-action'/> <flag name='virtio-blk.queue-size'/> <flag name='query-dirty-rate'/> + <flag name='calc-dirty-rate'/> <version>6000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>39100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml index b213abb..8ea688f 100644 --- a/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.0.0.x86_64.xml @@ -234,6 +234,7 @@ <flag name='piix4.acpi-root-pci-hotplug'/> <flag name='query-dirty-rate'/> <flag name='sev-inject-launch-secret'/> + <flag name='calc-dirty-rate'/> <version>6000000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml index d9bdcf9..ba1aecc 100644 --- a/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.1.0.x86_64.xml @@ -238,6 +238,7 @@ <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> <flag name='sev-inject-launch-secret'/> + <flag name='calc-dirty-rate'/> <version>6001000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml index f200a7d..17d563e 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.aarch64.xml @@ -202,6 +202,7 @@ <flag name='memory-backend-file.reserve'/> <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> + <flag name='calc-dirty-rate'/> <version>6001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml index ae5c1d3..eaa0ccc 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml @@ -199,6 +199,7 @@ <flag name='query-dirty-rate'/> <flag name='rbd-encryption'/> <flag name='sev-guest-kernel-hashes'/> + <flag name='calc-dirty-rate'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml index 103d00f..f3e86de 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -239,6 +239,7 @@ <flag name='rbd-encryption'/> <flag name='sev-guest-kernel-hashes'/> <flag name='sev-inject-launch-secret'/> + <flag name='calc-dirty-rate'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml index 88eee87..e9e9b43 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml @@ -200,6 +200,7 @@ <flag name='rbd-encryption'/> <flag name='sev-guest-kernel-hashes'/> <flag name='device.json+hotplug'/> + <flag name='calc-dirty-rate'/> <version>6002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml index 0753ac5..e28b48e 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -240,6 +240,7 @@ <flag name='sev-guest-kernel-hashes'/> <flag name='sev-inject-launch-secret'/> <flag name='device.json+hotplug'/> + <flag name='calc-dirty-rate'/> <version>6002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> Probing QEMU_CAPS_CALC_DIRTY_RATE capability in advance in case of failure when calculating dirty page rate. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/qemu/qemu_driver.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0a1ba74..0e8e9b1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20647,10 +20647,22 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, virQEMUDriver *driver = dom->conn->privateData; virDomainObj *vm = NULL; qemuDomainObjPrivate *priv; + g_autoptr(virQEMUCaps) qemucaps = NULL; int ret = -1; virCheckFlags(0, -1); + if (!(qemucaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL))) + return -1; + + if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_CALC_DIRTY_RATE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support calculating dirty page rate")); + return -1; + } + if (seconds < MIN_DIRTYRATE_CALC_PERIOD || seconds > MAX_DIRTYRATE_CALC_PERIOD) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> mode option of calc-dirty-rate command since qemu >=6.2.0. Introduce QEMU_CAPS_DIRTYRATE_MODE capability definition. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 1 + 6 files changed, 7 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index de08e81..367c286 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -658,6 +658,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 420 */ "device.json+hotplug", /* QEMU_CAPS_DEVICE_JSON */ "calc-dirty-rate", /* QEMU_CAPS_CALC_DIRTY_RATE */ + "dirtyrate-param.mode", /* QEMU_CAPS_DIRTYRATE_MODE */ ); @@ -1576,6 +1577,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "screendump/arg-type/device", QEMU_CAPS_SCREENDUMP_DEVICE }, { "set-numa-node/arg-type/+hmat-lb", QEMU_CAPS_NUMA_HMAT }, { "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, + { "calc-dirty-rate/arg-type/mode", QEMU_CAPS_DIRTYRATE_MODE }, }; typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 598cef9..329701c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -637,6 +637,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 420 */ QEMU_CAPS_DEVICE_JSON, /* -device accepts JSON (and works with hot-unplug) */ QEMU_CAPS_CALC_DIRTY_RATE, /* accepts calc-dirty-rate */ + QEMU_CAPS_DIRTYRATE_MODE , /* calc-dirty-rate accepts mode parameter */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml index eaa0ccc..9fe9c27 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml @@ -200,6 +200,7 @@ <flag name='rbd-encryption'/> <flag name='sev-guest-kernel-hashes'/> <flag name='calc-dirty-rate'/> + <flag name='dirtyrate-param.mode'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml index f3e86de..d77907a 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml @@ -240,6 +240,7 @@ <flag name='sev-guest-kernel-hashes'/> <flag name='sev-inject-launch-secret'/> <flag name='calc-dirty-rate'/> + <flag name='dirtyrate-param.mode'/> <version>6002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100244</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml index e9e9b43..5d7f283 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml @@ -201,6 +201,7 @@ <flag name='sev-guest-kernel-hashes'/> <flag name='device.json+hotplug'/> <flag name='calc-dirty-rate'/> + <flag name='dirtyrate-param.mode'/> <version>6002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900243</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml index e28b48e..6bc6e7f 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -241,6 +241,7 @@ <flag name='sev-inject-launch-secret'/> <flag name='device.json+hotplug'/> <flag name='calc-dirty-rate'/> + <flag name='dirtyrate-param.mode'/> <version>6002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100243</microcodeVersion> -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> Add mode option to extend qemuDomainStartDirtyRateCalc API, which is introduced since qemu >= 6.2. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 13 +++++++++++++ src/qemu/qemu_driver.c | 33 +++++++++++++++++++++++++++++++-- src/qemu/qemu_monitor.c | 5 +++-- src/qemu/qemu_monitor.h | 10 +++++++++- src/qemu/qemu_monitor_json.c | 26 +++++++++++++++++++++----- src/qemu/qemu_monitor_json.h | 3 ++- 6 files changed, 79 insertions(+), 11 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 4da1a63..54bb23b 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5257,6 +5257,19 @@ typedef enum { # endif } virDomainDirtyRateStatus; +/** + * virDomainDirtyRateCalcFlags: + * + * Flags OR'ed together to provide specific behaviour when calculating dirty page + * rate for a Domain + * + */ +typedef enum { + VIR_DOMAIN_DIRTYRATE_MODE_PAGE_SAMPLING = 0, /* default mode - page-sampling */ + VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP = 1 << 0, /* dirty-bitmap mode */ + VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING = 1 << 1, /* dirty-ring mode */ +} virDomainDirtyRateCalcFlags; + int virDomainStartDirtyRateCalc(virDomainPtr domain, int seconds, unsigned int flags); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0e8e9b1..feebfc4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20648,9 +20648,13 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, virDomainObj *vm = NULL; qemuDomainObjPrivate *priv; g_autoptr(virQEMUCaps) qemucaps = NULL; + qemuMonitorDirtyRateCalcMode calcmode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; + bool mode = false; int ret = -1; - virCheckFlags(0, -1); + virCheckFlags(VIR_DOMAIN_DIRTYRATE_MODE_PAGE_SAMPLING | + VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP | + VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING, -1); if (!(qemucaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache, NULL, NULL, NULL, NULL, @@ -20663,6 +20667,15 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, return -1; } + mode = virQEMUCapsGet(qemucaps, QEMU_CAPS_DIRTYRATE_MODE); + + if (!mode && (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP || + (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING))) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support calculating dirty page rate" + "with specified mode")); + } + if (seconds < MIN_DIRTYRATE_CALC_PERIOD || seconds > MAX_DIRTYRATE_CALC_PERIOD) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -20676,6 +20689,22 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, if (!(vm = qemuDomainObjFromDomain(dom))) return -1; + if (mode) { + /* libvirt-domain.c already guaranteed these two flags are exclusive. */ + if (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP) { + calcmode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_BITMAP; + } else if (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING) { + if (vm->def->features[VIR_DOMAIN_FEATURE_KVM] != VIR_TRISTATE_SWITCH_ON || + vm->def->kvm_features->features[VIR_DOMAIN_KVM_DIRTY_RING] != VIR_TRISTATE_SWITCH_ON) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("Calculating dirty page rate with dirty-ring requires" + "dirty-ring feature enabled.")); + goto cleanup; + } + calcmode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_RING; + } + } + if (virDomainStartDirtyRateCalcEnsureACL(dom->conn, vm->def) < 0) goto cleanup; @@ -20692,7 +20721,7 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, priv = vm->privateData; qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds); + ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds, calcmode); qemuDomainObjExitMonitor(driver, vm); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index babf9e6..b82a1a3 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4532,13 +4532,14 @@ qemuMonitorTransactionBackup(virJSONValue *actions, int qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, - int seconds) + int seconds, + qemuMonitorDirtyRateCalcMode mode) { VIR_DEBUG("seconds=%d", seconds); QEMU_CHECK_MONITOR(mon); - return qemuMonitorJSONStartDirtyRateCalc(mon, seconds); + return qemuMonitorJSONStartDirtyRateCalc(mon, seconds, mode); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 9b2e4e1..08e14c0 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1551,9 +1551,17 @@ qemuMonitorTransactionBackup(virJSONValue *actions, const char *bitmap, qemuMonitorTransactionBackupSyncMode syncmode); +typedef enum { + VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING = 0, + VIR_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_BITMAP, + VIR_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_RING, + VIR_DOMAIN_DIRTYRATE_CALC_MODE_LAST, +} qemuMonitorDirtyRateCalcMode; + int qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, - int seconds); + int seconds, + qemuMonitorDirtyRateCalcMode mode); typedef struct _qemuMonitorDirtyRateInfo qemuMonitorDirtyRateInfo; struct _qemuMonitorDirtyRateInfo { diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index b0b5136..afbd721 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8695,18 +8695,34 @@ qemuMonitorJSONGetCPUMigratable(qemuMonitor *mon, migratable); } +VIR_ENUM_DECL(qemuMonitorDirtyRateCalcMode); +VIR_ENUM_IMPL(qemuMonitorDirtyRateCalcMode, + VIR_DOMAIN_DIRTYRATE_CALC_MODE_LAST, + "page-sampling", + "dirty-bitmap", + "dirty-ring"); int qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon, - int seconds) + int seconds, + qemuMonitorDirtyRateCalcMode mode) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; - if (!(cmd = qemuMonitorJSONMakeCommand("calc-dirty-rate", - "i:calc-time", seconds, - NULL))) - return -1; + if (mode == VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING) { + if (!(cmd = qemuMonitorJSONMakeCommand("calc-dirty-rate", + "i:calc-time", seconds, + NULL))) + return -1; + } else { + const char *modestr = qemuMonitorDirtyRateCalcModeTypeToString(mode); + if (!(cmd = qemuMonitorJSONMakeCommand("calc-dirty-rate", + "i:calc-time", seconds, + "s:mode", modestr, + NULL))) + return -1; + } if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) return -1; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 64d9ebd..51f78f1 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -855,7 +855,8 @@ qemuMonitorJSONGetCPUMigratable(qemuMonitor *mon, int qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon, - int seconds); + int seconds, + qemuMonitorDirtyRateCalcMode mode); int qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon, -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> Extend domdirtyrate-calc virsh api with mode option, either of these three options "page-sampling,dirty-bitmap,dirty-ring" can be specified when calculating dirty page rate. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- docs/manpages/virsh.rst | 7 +++++-- src/libvirt-domain.c | 12 +++++++++++- tools/virsh-domain.c | 28 +++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index e28927e..e09703c 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1714,13 +1714,16 @@ domdirtyrate-calc :: domdirtyrate-calc <domain> [--seconds <sec>] + [{--page-sampling | --dirty-bitmap | --dirty-ring}] Calculate an active domain's memory dirty rate which may be expected by user in order to decide whether it's proper to be migrated out or not. The ``seconds`` parameter can be used to calculate dirty rate in a specific time which allows 60s at most now and would be default to 1s -if missing. The calculated dirty rate information is available by calling -'domstats --dirtyrate'. +if missing. These three *--page-sampling, --dirty-bitmap, --dirty-ring* +paremeters are mutually exclusive and used to specify calculation mode, +*--page-sampling* is the default mode if missing. The calculated dirty +rate information is available by calling 'domstats --dirtyrate'. domdisplay diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 5912551..4caa740 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -13298,7 +13298,7 @@ virDomainGetMessages(virDomainPtr domain, * virDomainStartDirtyRateCalc: * @domain: a domain object * @seconds: specified calculating time in seconds - * @flags: extra flags; not used yet, so callers should always pass 0 + * @flags: bitwise-OR of supported virDomainDirtyRateCalcFlags * * Calculate the current domain's memory dirty rate in next @seconds. * The calculated dirty rate information is available by calling @@ -13322,6 +13322,16 @@ virDomainStartDirtyRateCalc(virDomainPtr domain, virCheckReadOnlyGoto(conn->flags, error); + VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_DIRTYRATE_MODE_PAGE_SAMPLING, + VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP, + error); + VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_DIRTYRATE_MODE_PAGE_SAMPLING, + VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING, + error); + VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP, + VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING, + error); + if (conn->driver->domainStartDirtyRateCalc) { int ret; ret = conn->driver->domainStartDirtyRateCalc(domain, seconds, flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b56f6a9..a032f70 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -14465,6 +14465,20 @@ static const vshCmdOptDef opts_domdirtyrate_calc[] = { .help = N_("calculate memory dirty rate within specified seconds, " "the supported value range from 1 to 60, default to 1.") }, + {.name = "page-sampling", + .type = VSH_OT_BOOL, + .help = N_("dirty page rate is calculated by sampling memory.") + }, + {.name = "dirty-bitmap", + .type = VSH_OT_BOOL, + .help = N_("dirty page rate is calculated by recording dirty bitmap " + "during calculation period.") + }, + {.name = "dirty-ring", + .type = VSH_OT_BOOL, + .help = N_("dirty page rate is calculated by recording dirty pages " + "for a virtual CPU when dirty-ring feature enabled.") + }, {.name = NULL} }; @@ -14473,6 +14487,7 @@ cmdDomDirtyRateCalc(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshDomain) dom = NULL; int seconds = 1; /* the default value is 1 */ + unsigned int flags = 0; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; @@ -14480,7 +14495,18 @@ cmdDomDirtyRateCalc(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptInt(ctl, cmd, "seconds", &seconds) < 0) return false; - if (virDomainStartDirtyRateCalc(dom, seconds, 0) < 0) + if (vshCommandOptBool(cmd, "page-sampling")) + flags |= VIR_DOMAIN_DIRTYRATE_MODE_PAGE_SAMPLING; + if (vshCommandOptBool(cmd, "dirty-bitmap")) + flags |= VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP;; + if (vshCommandOptBool(cmd, "dirty-ring")) + flags |= VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING;; + + VSH_EXCLUSIVE_OPTIONS("page-sampling", "dirty-bitmap"); + VSH_EXCLUSIVE_OPTIONS("page-sampling", "dirty-ring"); + VSH_EXCLUSIVE_OPTIONS("dirty-bitmap", "dirty-ring"); + + if (virDomainStartDirtyRateCalc(dom, seconds, flags) < 0) return false; vshPrintExtra(ctl, _("Start to calculate domain's memory " -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> Add calc_mode for dirtyrate statistics retured by virsh domstats --dirtyrate api, also add vcpu dirtyrate if dirty-ring mode was used in last measurement. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/libvirt-domain.c | 5 +++++ src/qemu/qemu_driver.c | 14 ++++++++++++ src/qemu/qemu_monitor.h | 10 +++++++++ src/qemu/qemu_monitor_json.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 4caa740..b1b6707 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11941,6 +11941,11 @@ virConnectGetDomainCapabilities(virConnectPtr conn, * "dirtyrate.megabytes_per_second" - the calculated memory dirty rate in * MiB/s as long long. It is produced * only if the calc_status is measured. + * "dirtyrate.calc_mode" - the calculation mode used last measurement as int, + * which is one of qemuMonitorDirtyRateCalcMode enum. + * "dirtyrate.vcpu.<num>.megabytes_per_second" - the calculated memory dirty + * rate for a virtual cpu as + * long long. * * Note that entire stats groups or individual stat fields may be missing from * the output in case they are not supported by the given hypervisor, are not diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index feebfc4..09eda6b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18537,6 +18537,20 @@ qemuDomainGetStatsDirtyRate(virQEMUDriver *driver, "dirtyrate.megabytes_per_second") < 0) return -1; + if (virTypedParamListAddInt(params, info.mode, + "dirtyrate.calc_mode") < 0) + return -1; + + if (info.mode == VIR_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_RING) { + int i; + for (i = 0; i < info.nvcpus; i++) { + if (virTypedParamListAddLLong(params, info.rates[i].value, + "dirtyrate.vcpu.%d.megabytes_per_second", + info.rates[i].index) < 0) + return -1; + } + } + return 0; } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 08e14c0..465feef 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1563,6 +1563,12 @@ qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, int seconds, qemuMonitorDirtyRateCalcMode mode); +typedef struct _qemuMonitorDirtyRateVcpu qemuMonitorDirtyRateVcpu; +struct _qemuMonitorDirtyRateVcpu { + int index; /* virtual cpu index */ + long long value; /* virtual cpu dirty page rate in MB/s */ +}; + typedef struct _qemuMonitorDirtyRateInfo qemuMonitorDirtyRateInfo; struct _qemuMonitorDirtyRateInfo { int status; /* the status of last dirtyrate calculation, @@ -1570,6 +1576,10 @@ struct _qemuMonitorDirtyRateInfo { int calcTime; /* the period of dirtyrate calculation */ long long startTime; /* the start time of dirtyrate calculation */ long long dirtyRate; /* the dirtyrate in MiB/s */ + qemuMonitorDirtyRateCalcMode mode; /* calculation mode used in + last measurement */ + size_t nvcpus; /* number of virtual cpu */ + qemuMonitorDirtyRateVcpu *rates; /* array of dirty page rate */ }; int diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index afbd721..391f685 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8741,11 +8741,45 @@ VIR_ENUM_IMPL(qemuMonitorDirtyRateStatus, "measured"); static int +qemuMonitorJSONExtractVcpuDirtyRate(virJSONValue *data, + qemuMonitorDirtyRateInfo *info) +{ + size_t nvcpus; + int i; + + nvcpus = virJSONValueArraySize(data); + info->nvcpus = nvcpus; + info->rates = g_new0(qemuMonitorDirtyRateVcpu, nvcpus); + + for (i = 0; i < nvcpus; i++) { + virJSONValue *entry = virJSONValueArrayGet(data, i); + if (virJSONValueObjectGetNumberInt(entry, "id", + &info->rates[i].index) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-dirty-rate reply was missing 'id' data")); + return -1; + } + + if (virJSONValueObjectGetNumberLong(entry, "dirty-rate", + &info->rates[i].value) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-dirty-rate reply was missing 'dirty-rate' data")); + return -1; + } + } + + return 0; +} + +static int qemuMonitorJSONExtractDirtyRateInfo(virJSONValue *data, qemuMonitorDirtyRateInfo *info) { const char *statusstr; + const char *modestr; int status; + int mode; + virJSONValue *rates = NULL; if (!(statusstr = virJSONValueObjectGetString(data, "status"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -8782,6 +8816,24 @@ qemuMonitorJSONExtractDirtyRateInfo(virJSONValue *data, return -1; } + info->mode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; + if ((modestr = virJSONValueObjectGetString(data, "mode"))) { + if ((mode = qemuMonitorDirtyRateCalcModeTypeFromString(modestr)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown dirtyrate calculation mode: %s"), modestr); + return -1; + } + info->mode = mode; + } + + if ((rates = virJSONValueObjectGetArray(data, "vcpu-dirty-rate"))) { + if (qemuMonitorJSONExtractVcpuDirtyRate(rates, info) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-dirty-rate parsing 'vcpu-dirty-rate' in failure")); + return -1; + } + } + return 0; } -- 1.8.3.1
participants (1)
-
huangy81@chinatelecom.cn