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

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> 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(黄勇) (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 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 | 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

On Thu, Jan 27, 2022 at 15:25:18 +0800, 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 | 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;
This is not needed, qemuCaps for a running vm are stored in 'priv->qemuCaps'. In fact it's wrong to not use the stored capabilities.
+ + if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_CALC_DIRTY_RATE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support calculating dirty page rate")); + return -1; + }
Obviously the code will need to be moved to a place where 'priv' is already populated.
+ if (seconds < MIN_DIRTYRATE_CALC_PERIOD || seconds > MAX_DIRTYRATE_CALC_PERIOD) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, -- 1.8.3.1

在 2022/1/27 16:23, Peter Krempa 写道:
On Thu, Jan 27, 2022 at 15:25:18 +0800, 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 | 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;
This is not needed, qemuCaps for a running vm are stored in 'priv->qemuCaps'. In fact it's wrong to not use the stored capabilities

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> 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

On Thu, Jan 27, 2022 at 15:25:20 +0800, huangy81@chinatelecom.cn wrote:
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);
Same issue as I've pointed out previously, you must use priv->qemuCaps. Also you can then merge the two blocks which are guarded by 'mode' and get rid of the extra variable.
+ + 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"));
Here you are missing a goto cleanup or similar jump-out statement. Also please observe error messages in new code should not be line-broken even if the line will exceed 80 columns: https://www.libvirt.org/coding-style.html#error-message-format
+ }
+ 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. */
There isn't any code being added which would guarantee that, so the comment is either to be removed or something's missing in this commit.
+ 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",
All of this code must be moved below the ACL check or otherwise it could leak information about the VM object to users unauthorized to even see the VM object.
+ _("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);
[...]
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; + }
You don't have to use two invocations of qemuMonitorJSONMakeCommand, but rather use 'S' for formatting the string which doesn't output the field if the string is null, so the code should look like: const char *modestr = NULL; if (mode != VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING) modestr = qemuMonitorDirtyRateCalcModeTypeToString(mode); if (!(cmd = qemuMonitorJSONMakeCommand("calc-dirty-rate", "i:calc-time", seconds, "S:mode", modestr, NULL)))

在 2022/1/27 16:34, Peter Krempa 写道:
On Thu, Jan 27, 2022 at 15:25:20 +0800, huangy81@chinatelecom.cn wrote:
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);
Same issue as I've pointed out previously, you must use priv->qemuCaps.
Ok, i'll fix it
Also you can then merge the two blocks which are guarded by 'mode' and get rid of the extra variable.
+ + 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"));
Here you are missing a goto cleanup or similar jump-out statement.
Also please observe error messages in new code should not be line-broken even if the line will exceed 80 columns:
https://www.libvirt.org/coding-style.html#error-message-format
+ }
+ 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. */
There isn't any code being added which would guarantee that, so the comment is either to be removed or something's missing in this commit.
+ 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",
All of this code must be moved below the ACL check or otherwise it could leak information about the VM object to users unauthorized to even see the VM object.
+ _("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);
[...]
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; + }
You don't have to use two invocations of qemuMonitorJSONMakeCommand, but rather use 'S' for formatting the string which doesn't output the field if the string is null, so the code should look like:
const char *modestr = NULL;
if (mode != VIR_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING) modestr = qemuMonitorDirtyRateCalcModeTypeToString(mode);
if (!(cmd = qemuMonitorJSONMakeCommand("calc-dirty-rate", "i:calc-time", seconds, "S:mode", modestr, NULL)))
Sound good, :) -- Best regard Hyman Huang(黄勇)

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

On Thu, Jan 27, 2022 at 15:25:21 +0800, 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 +++++++++++- 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);
Okay, so this clarifies what happened in the last commit. You've misplaced this here. Ideally separate the libvirt-domain.c/h changes into a separate commit, then after them do the virsh commit and after that the commit adding implementation in the qemu driver.
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
[...]
@@ -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");
We usually do these validations first, before using the options to calculate flags.
+ + 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

On Thu, Jan 27, 2022 at 15:25:22 +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..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.
'qemuMonitorDirtyRateCalcMode' is an internal qemu-private enum. You can't use it in the public API as the appropriate constants are not exported and also we are free to change meanings of internal constants.
+ * "dirtyrate.vcpu.<num>.megabytes_per_second" - the calculated memory dirty + * rate for a virtual cpu as + * long long.
A signed value doesn't really seem make too much sense to a value which can't be negative.
* * 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)
Please align it properly even if it exceeds 80 colums.
+ return -1; + } + } + return 0; }
[...]
participants (3)
-
huangy81@chinatelecom.cn
-
Hyman Huang
-
Peter Krempa