[PATCH v3 0/7] support mode option for dirtyrate calculation

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> v3: - Rebase the master - [PATCH v2 2/6]: Fix the usage of virQEMUCapsGet - [PATCH v2 4/6]: Fix the cleanup missed in qemuDomainStartDirtyRateCalc - [PATCH v2 4/6]: Move all blocks below ACL check - [PATCH v2 4/6]: Make the qemuMonitorJSONStartDirtyRateCalc cleaner by merging the different case of qemuMonitorJSONMakeCommand - [PATCH v2 4/6]: Code clean, make the error message not be line-broken - [PATCH v2 5/6]: Abstract the enum definition into a standalone commit - [PATCH v2 5/6]: Move the validations code above calculating flags block - [PATCH v2 6/6]: Change the type of 'value' field to unsigned in struct qemuMonitorDirtyRateVcpu - [PATCH v2 6/6]: Rename the enum type qemuMonitorDirtyRateCalcMode to virDomainDirtyRateCalcMode - [PATCH v2 6/6]: Code clean, align the code in qemuDomainGetStatsDirtyRate Thanks Peter for quick and precise response, please review. Regards Yong v2: Rebase master and fix confilicts with commit "Introduce QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC" Thanks ! 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(黄勇) (7): 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 include: Introduce enum for qemuDomainStartDirtyRateCalc qemu_driver: Add mode parameter to qemuDomainStartDirtyRateCalc virsh: Add mode option to domdirtyrate-calc virsh api qemu_driver: Add calc_mode for dirtyrate statistics docs/manpages/virsh.rst | 7 ++- include/libvirt/libvirt-domain.h | 24 ++++++++ src/libvirt-domain.c | 17 +++++- src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_driver.c | 48 +++++++++++++++- src/qemu/qemu_monitor.c | 5 +- src/qemu/qemu_monitor.h | 13 ++++- src/qemu/qemu_monitor_json.c | 69 ++++++++++++++++++++++- 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, 226 insertions(+), 12 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 1b28c3f..968185e 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -663,6 +663,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "device.json+hotplug", /* QEMU_CAPS_DEVICE_JSON */ "hvf", /* QEMU_CAPS_HVF */ "virtio-mem-pci.prealloc", /* QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC */ + "calc-dirty-rate", /* QEMU_CAPS_CALC_DIRTY_RATE */ ); @@ -1229,6 +1230,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 6ff0b7a..a295bf0 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -638,6 +638,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_DEVICE_JSON, /* -device accepts JSON (and works with hot-unplug) */ QEMU_CAPS_HVF, /* Whether Hypervisor.framework is available */ QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC, /* -device virtio-mem-pci.prealloc= */ + 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 07d49a8..9ca33f9 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='virtio-mem-pci.prealloc'/> + <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 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0a1ba74..c8ee897 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20679,6 +20679,12 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, VIR_DEBUG("Calculate dirty rate in next %d seconds", seconds); priv = vm->privateData; + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CALC_DIRTY_RATE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support calculating dirty page rate")); + goto endjob; + } + qemuDomainObjEnterMonitor(driver, vm); ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds); -- 1.8.3.1

On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
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 | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0a1ba74..c8ee897 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20679,6 +20679,12 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, VIR_DEBUG("Calculate dirty rate in next %d seconds", seconds);
priv = vm->privateData; + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CALC_DIRTY_RATE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support calculating dirty page rate")); + goto endjob; + } + qemuDomainObjEnterMonitor(driver, vm); ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds);
This can be done before BeginJob(); because acquiring a job is needless (and possibly blocking) operation if we know upfront that QEMU doesn't support what we need. Moving 'priv = vm->privateData' line is perfectly okay. Michal

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 968185e..529e9ce 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -664,6 +664,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "hvf", /* QEMU_CAPS_HVF */ "virtio-mem-pci.prealloc", /* QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC */ "calc-dirty-rate", /* QEMU_CAPS_CALC_DIRTY_RATE */ + "dirtyrate-param.mode", /* QEMU_CAPS_DIRTYRATE_MODE */ ); @@ -1622,6 +1623,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 a295bf0..f6188b4 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -639,6 +639,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_HVF, /* Whether Hypervisor.framework is available */ QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC, /* -device virtio-mem-pci.prealloc= */ 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 9ca33f9..ae800ab 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml @@ -242,6 +242,7 @@ <flag name='device.json+hotplug'/> <flag name='virtio-mem-pci.prealloc'/> <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> Introduce virDomainDirtyRateCalcFlags and virDomainDirtyRateCalcMode to get ready for adding mode parameter to qemuDomainStartDirtyRateCalc. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 374859f..722a310 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5257,8 +5257,32 @@ 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); +/** + * virDomainDirtyRateCalcMode: + * + * Dirty page rate calculation mode used during measurement. + */ +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, +} virDomainDirtyRateCalcMode; #endif /* LIBVIRT_DOMAIN_H */ -- 1.8.3.1

On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn>
Introduce virDomainDirtyRateCalcFlags and virDomainDirtyRateCalcMode to get ready for adding mode parameter to qemuDomainStartDirtyRateCalc.
Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 374859f..722a310 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5257,8 +5257,32 @@ 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);
Up until here it's okay.
+/** + * virDomainDirtyRateCalcMode: + * + * Dirty page rate calculation mode used during measurement. + */ +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, +} virDomainDirtyRateCalcMode;
#endif /* LIBVIRT_DOMAIN_H */
But this doesn't belong here. These flags are used only internally. Why they need to be exposed? Michal

在 2022/2/14 18:13, Michal Prívozník 写道:
On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn>
Introduce virDomainDirtyRateCalcFlags and virDomainDirtyRateCalcMode to get ready for adding mode parameter to qemuDomainStartDirtyRateCalc.
Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 374859f..722a310 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5257,8 +5257,32 @@ 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);
Up until here it's okay.
+/** + * virDomainDirtyRateCalcMode: + * + * Dirty page rate calculation mode used during measurement. + */ +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, +} virDomainDirtyRateCalcMode;
#endif /* LIBVIRT_DOMAIN_H */
But this doesn't belong here. These flags are used only internally. Why they need to be exposed?
When displaying the dirtyrate info in 'virsh domstats --dirtyrate' api, we introduce the 'mode' field to show what mode used last calculation. Whose meanings can be refered to the virDomainDirtyRateCalcMode
Michal
-- Best regard Hyman Huang(黄勇)

On 2/14/22 12:21, Hyman Huang wrote:
When displaying the dirtyrate info in 'virsh domstats --dirtyrate' api, we introduce the 'mode' field to show what mode used last calculation. Whose meanings can be refered to the virDomainDirtyRateCalcMode
Oh, I did not realize that. In that case it's okay if this stays here. Michal

On Mon, Feb 14, 2022 at 07:21:58PM +0800, Hyman Huang wrote:
在 2022/2/14 18:13, Michal Prívozník 写道:
On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn>
Introduce virDomainDirtyRateCalcFlags and virDomainDirtyRateCalcMode to get ready for adding mode parameter to qemuDomainStartDirtyRateCalc.
Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 374859f..722a310 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5257,8 +5257,32 @@ 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);
Up until here it's okay.
+/** + * virDomainDirtyRateCalcMode: + * + * Dirty page rate calculation mode used during measurement. + */ +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, +} virDomainDirtyRateCalcMode; #endif /* LIBVIRT_DOMAIN_H */
But this doesn't belong here. These flags are used only internally. Why they need to be exposed?
When displaying the dirtyrate info in 'virsh domstats --dirtyrate' api, we introduce the 'mode' field to show what mode used last calculation. Whose meanings can be refered to the virDomainDirtyRateCalcMode
The 'mode' should be exposed in string format. We don't put enum integer values into virTypedParameter fields normally, because we expect clients to be robust against new enum values being added at a later date. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

在 2022/2/14 19:31, Daniel P. Berrangé 写道:
On Mon, Feb 14, 2022 at 07:21:58PM +0800, Hyman Huang wrote:
在 2022/2/14 18:13, Michal Prívozník 写道:
On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn>
Introduce virDomainDirtyRateCalcFlags and virDomainDirtyRateCalcMode to get ready for adding mode parameter to qemuDomainStartDirtyRateCalc.
Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 374859f..722a310 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5257,8 +5257,32 @@ 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);
Up until here it's okay.
+/** + * virDomainDirtyRateCalcMode: + * + * Dirty page rate calculation mode used during measurement. + */ +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, +} virDomainDirtyRateCalcMode; #endif /* LIBVIRT_DOMAIN_H */
But this doesn't belong here. These flags are used only internally. Why they need to be exposed?
When displaying the dirtyrate info in 'virsh domstats --dirtyrate' api, we introduce the 'mode' field to show what mode used last calculation. Whose meanings can be refered to the virDomainDirtyRateCalcMode
The 'mode' should be exposed in string format. We don't put enum integer values into virTypedParameter fields normally, because we expect clients to be robust against new enum values being added at a later date.
Indeed, originally i think it seems werid, but since dirtyrate.calc_status alrealy implemented the same way, i didn't think about this more carefully. "dirtyrate.calc_status" - the status of last memory dirty rate calculation. I'll modify this next version and more importantly, it will be consistent with virsh domdirtyrate-calc parameter "--mode=[page-samling|dirty-bitmap|dirty-ring]"
Regards, Daniel
-- Best regard Hyman Huang(黄勇)

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> Add mode parameter to qemuDomainStartDirtyRateCalc API, 'mode' option of 'calc-dirty-rate' command was introduced since qemu >= 6.2. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/qemu/qemu_driver.c | 4 +++- src/qemu/qemu_monitor.c | 5 +++-- src/qemu/qemu_monitor.h | 3 ++- src/qemu/qemu_monitor_json.c | 17 +++++++++++++++-- src/qemu/qemu_monitor_json.h | 3 ++- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c8ee897..cb2af61 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20647,6 +20647,8 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, virQEMUDriver *driver = dom->conn->privateData; virDomainObj *vm = NULL; qemuDomainObjPrivate *priv; + virDomainDirtyRateCalcMode mode = + VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; int ret = -1; virCheckFlags(0, -1); @@ -20686,7 +20688,7 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, } qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds); + ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds, mode); qemuDomainObjExitMonitor(driver, vm); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index babf9e6..e97fe4e 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, + virDomainDirtyRateCalcMode 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..6d43f23 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1553,7 +1553,8 @@ qemuMonitorTransactionBackup(virJSONValue *actions, int qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, - int seconds); + int seconds, + virDomainDirtyRateCalcMode 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..8d62ca7 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8695,18 +8695,31 @@ qemuMonitorJSONGetCPUMigratable(qemuMonitor *mon, migratable); } +VIR_ENUM_DECL(virDomainDirtyRateCalcMode); +VIR_ENUM_IMPL(virDomainDirtyRateCalcMode, + VIR_DOMAIN_DIRTYRATE_CALC_MODE_LAST, + "page-sampling", + "dirty-bitmap", + "dirty-ring"); int qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon, - int seconds) + int seconds, + virDomainDirtyRateCalcMode mode) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; + const char *modestr = NULL; + + if (mode != VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING) + modestr = virDomainDirtyRateCalcModeTypeToString(mode); if (!(cmd = qemuMonitorJSONMakeCommand("calc-dirty-rate", "i:calc-time", seconds, - NULL))) + "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..2056a03 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, + virDomainDirtyRateCalcMode mode); int qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon, -- 1.8.3.1

On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn>
Add mode parameter to qemuDomainStartDirtyRateCalc API, 'mode' option of 'calc-dirty-rate' command was introduced since qemu >= 6.2.
Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/qemu/qemu_driver.c | 4 +++- src/qemu/qemu_monitor.c | 5 +++-- src/qemu/qemu_monitor.h | 3 ++- src/qemu/qemu_monitor_json.c | 17 +++++++++++++++-- src/qemu/qemu_monitor_json.h | 3 ++- 5 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index c8ee897..cb2af61 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20647,6 +20647,8 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, virQEMUDriver *driver = dom->conn->privateData; virDomainObj *vm = NULL; qemuDomainObjPrivate *priv; + virDomainDirtyRateCalcMode mode = + VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING;
It's okay if this is all on one line. It's more readable that way anyway. The limit for 80 characters is more of a recommendation and due to way we construct names it's easy to reach pretty soon. The aim of the rule is to make code more readable. And I find it more readable when on one line. Therefore, in this particular example it's okay of the line is longer. Michal

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 +++++++++++- src/qemu/qemu_driver.c | 24 +++++++++++++++++++++++- tools/virsh-domain.c | 28 +++++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 5 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/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index cb2af61..5c2f289 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20651,7 +20651,9 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; 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 (seconds < MIN_DIRTYRATE_CALC_PERIOD || seconds > MAX_DIRTYRATE_CALC_PERIOD) { @@ -20687,6 +20689,26 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, goto endjob; } + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DIRTYRATE_MODE)) { + /* libvirt-domain.c already guaranteed these two flags are exclusive. */ + if (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP) { + mode = 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", + _("dirty-ring calculation mode requires dirty-ring feature enabled.")); + goto endjob; + } + mode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_RING; + } + } else if ((flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP || + (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING))) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support dirty page rate calculation mode")); + goto endjob; + } + qemuDomainObjEnterMonitor(driver, vm); ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds, mode); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index b56f6a9..29d8f9a 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) + VSH_EXCLUSIVE_OPTIONS("page-sampling", "dirty-bitmap"); + VSH_EXCLUSIVE_OPTIONS("page-sampling", "dirty-ring"); + VSH_EXCLUSIVE_OPTIONS("dirty-bitmap", "dirty-ring"); + + 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;; + + if (virDomainStartDirtyRateCalc(dom, seconds, flags) < 0) return false; vshPrintExtra(ctl, _("Start to calculate domain's memory " -- 1.8.3.1

On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
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 +++++++++++- src/qemu/qemu_driver.c | 24 +++++++++++++++++++++++- tools/virsh-domain.c | 28 +++++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 5 deletions(-)
These changes need to be broken into smaller patches. Modifying virsh is one patch, qemu driver is the other.
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}]
I'm wondering whether we should go with domdirtyrate-calc $dom --mode=[page-samling|dirty-bitmap|dirty-ring] instead. My reasoning is that it's more user friendly, IMO. But I don't have strong opinion, your version is good too.
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/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index cb2af61..5c2f289 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20651,7 +20651,9 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; 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 (seconds < MIN_DIRTYRATE_CALC_PERIOD || seconds > MAX_DIRTYRATE_CALC_PERIOD) { @@ -20687,6 +20689,26 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, goto endjob; }
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DIRTYRATE_MODE)) { + /* libvirt-domain.c already guaranteed these two flags are exclusive. */ + if (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP) { + mode = 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", + _("dirty-ring calculation mode requires dirty-ring feature enabled.")); + goto endjob; + } + mode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_RING; + } + } else if ((flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP || + (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING))) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support dirty page rate calculation mode")); + goto endjob; + } +
Again, this is something that could be done before acquiring domain job. And if I may suggest slightly different implementation: have the code that sets @mode first, without checking for qemuCaps and save that bit for the end: if (mode != VIR_DOMAIN_DIRTYRATE_MODE_PAGE_SAMPLING && virQEMUCapsGet(priv->qemuCaps)) { error } That allows you to drop one level of nesting, which again improves readability.
qemuDomainObjEnterMonitor(driver, vm); ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds, mode);
Michal

在 2022/2/14 18:13, Michal Prívozník 写道:
On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
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 +++++++++++- src/qemu/qemu_driver.c | 24 +++++++++++++++++++++++- tools/virsh-domain.c | 28 +++++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 5 deletions(-)
These changes need to be broken into smaller patches. Modifying virsh is one patch, qemu driver is the other.
Ok.
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}]
I'm wondering whether we should go with domdirtyrate-calc $dom --mode=[page-samling|dirty-bitmap|dirty-ring] instead. My reasoning is that it's more user friendly, IMO. But I don't have strong opinion, your version is good too.
Indeed, these 3 modes are mutually exclusive, it's more sensible to use the --mode=[page-samling|dirty-bitmap|dirty-ring] instead. I'll do the modification next verison.
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

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..afc0c1b 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 virDomainDirtyRateCalcMode enum. + * "dirtyrate.vcpu.<num>.megabytes_per_second" - the calculated memory dirty + * rate for a virtual cpu as + * unsigned 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 5c2f289..3ef9569 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 (virTypedParamListAddULLong(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 6d43f23..1e500ce 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1556,6 +1556,12 @@ qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, int seconds, virDomainDirtyRateCalcMode mode); +typedef struct _qemuMonitorDirtyRateVcpu qemuMonitorDirtyRateVcpu; +struct _qemuMonitorDirtyRateVcpu { + int index; /* virtual cpu index */ + unsigned 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, @@ -1563,6 +1569,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 */ + virDomainDirtyRateCalcMode 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 8d62ca7..f088300 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8738,11 +8738,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 (virJSONValueObjectGetNumberUlong(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", @@ -8779,6 +8813,24 @@ qemuMonitorJSONExtractDirtyRateInfo(virJSONValue *data, return -1; } + info->mode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; + if ((modestr = virJSONValueObjectGetString(data, "mode"))) { + if ((mode = virDomainDirtyRateCalcModeTypeFromString(modestr)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown dirty page rate 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

On 1/28/22 08:35, huangy81@chinatelecom.cn wrote:
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..afc0c1b 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 virDomainDirtyRateCalcMode enum. + * "dirtyrate.vcpu.<num>.megabytes_per_second" - the calculated memory dirty + * rate for a virtual cpu as + * unsigned 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 5c2f289..3ef9569 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 (virTypedParamListAddULLong(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 6d43f23..1e500ce 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1556,6 +1556,12 @@ qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, int seconds, virDomainDirtyRateCalcMode mode);
+typedef struct _qemuMonitorDirtyRateVcpu qemuMonitorDirtyRateVcpu; +struct _qemuMonitorDirtyRateVcpu { + int index; /* virtual cpu index */ + unsigned 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, @@ -1563,6 +1569,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 */ + virDomainDirtyRateCalcMode 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 8d62ca7..f088300 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8738,11 +8738,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 (virJSONValueObjectGetNumberUlong(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", @@ -8779,6 +8813,24 @@ qemuMonitorJSONExtractDirtyRateInfo(virJSONValue *data, return -1; }
+ info->mode = VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING;
1: ^^^
+ if ((modestr = virJSONValueObjectGetString(data, "mode"))) { + if ((mode = virDomainDirtyRateCalcModeTypeFromString(modestr)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown dirty page rate calculation mode: %s"), modestr); + return -1; + } + info->mode = mode; + }
maybe move [1] into an else branch here? Otherwise looking good.
+ + 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; }
Michal

On Fri, Jan 28, 2022 at 03:35:54PM +0800, huangy81@chinatelecom.cn wrote:
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..afc0c1b 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 virDomainDirtyRateCalcMode enum.
Definitely don't do this. For any virTypedParameter API normal practice is to use a string to expose the data, not the rather enum integer value. This unusual approach is why you needed to add the internal enum def to the public header file earlier. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Ping for this patchset. Thanks, Yong 在 2022/1/28 15:35, huangy81@chinatelecom.cn 写道:
From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn>
v3: - Rebase the master - [PATCH v2 2/6]: Fix the usage of virQEMUCapsGet - [PATCH v2 4/6]: Fix the cleanup missed in qemuDomainStartDirtyRateCalc - [PATCH v2 4/6]: Move all blocks below ACL check - [PATCH v2 4/6]: Make the qemuMonitorJSONStartDirtyRateCalc cleaner by merging the different case of qemuMonitorJSONMakeCommand - [PATCH v2 4/6]: Code clean, make the error message not be line-broken - [PATCH v2 5/6]: Abstract the enum definition into a standalone commit - [PATCH v2 5/6]: Move the validations code above calculating flags block - [PATCH v2 6/6]: Change the type of 'value' field to unsigned in struct qemuMonitorDirtyRateVcpu - [PATCH v2 6/6]: Rename the enum type qemuMonitorDirtyRateCalcMode to virDomainDirtyRateCalcMode - [PATCH v2 6/6]: Code clean, align the code in qemuDomainGetStatsDirtyRate
Thanks Peter for quick and precise response, please review.
Regards
Yong
v2: Rebase master and fix confilicts with commit "Introduce QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_PREALLOC"
Thanks !
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(黄勇) (7): 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 include: Introduce enum for qemuDomainStartDirtyRateCalc qemu_driver: Add mode parameter to qemuDomainStartDirtyRateCalc virsh: Add mode option to domdirtyrate-calc virsh api qemu_driver: Add calc_mode for dirtyrate statistics
docs/manpages/virsh.rst | 7 ++- include/libvirt/libvirt-domain.h | 24 ++++++++ src/libvirt-domain.c | 17 +++++- src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_driver.c | 48 +++++++++++++++- src/qemu/qemu_monitor.c | 5 +- src/qemu/qemu_monitor.h | 13 ++++- src/qemu/qemu_monitor_json.c | 69 ++++++++++++++++++++++- 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, 226 insertions(+), 12 deletions(-)
participants (5)
-
Daniel P. Berrangé
-
huangy81@chinatelecom.cn
-
Hyman
-
Hyman Huang
-
Michal Prívozník