[PATCH v4 0/9] support mode option for dirtyrate calculation

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> v4: - Rebase the master - [PATCH v4 1/9]: Refactor dirty page rate calculation status implementation, display calc_status as string when 'virsh domstats --dirtyrate' api return. - [PATCH v4 3/9]: Adjust the 'cap check' block before BeginJob(). - [PATCH v4 5/9]: Drop the virDomainDirtyRateCalcMode and introduce internal enum qemuMonitorDirtyRateCalcMode instead. - [PATCH v4 6/9]: Code clean. - [PATCH v4 7/9]: Split qemu_driver logic of domdirtyrate-calc virsh api into a separate commit. - [PATCH v4 8/9]: Change the 'mode' parameter usage as --mode=[xxx|yyy], code clean in qemuDomainStartDirtyRateCalc. - [PATCH v4 9/9]: Display calc_mode as string and do code clean in qemuMonitorJSONExtractDirtyRateInfo. Thanks Michal and Peter for reviewing the previous versions, please review. Regards Yong 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(黄勇) (9): qemu: Refactor dirty page rate calculation status implementation 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 virDomainDirtyRateCalcFlags qemu_driver: Add mode parameter to qemuDomainStartDirtyRateCalc qemu_driver: Extend flags parameter of virDomainStartDirtyRateCalc 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 | 21 +++---- src/libvirt-domain.c | 20 +++++-- src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_driver.c | 63 +++++++++++++++++--- src/qemu/qemu_monitor.c | 5 +- src/qemu/qemu_monitor.h | 45 +++++++++++++- src/qemu/qemu_monitor_json.c | 72 +++++++++++++++++++++-- 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-completer-domain.c | 17 ++++++ tools/virsh-completer-domain.h | 4 ++ tools/virsh-domain.c | 42 ++++++++++++- tools/virsh-domain.h | 9 +++ 28 files changed, 294 insertions(+), 38 deletions(-) -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> For any virTypedParameter API normal practice is to use a string to expose the data, not the rather enum integer value. So let's drop the virDomainDirtyRateStatus in public header file and introduce internal enum def qemuMonitorDirtyRateStatus to describe the dirty page rate calculation status. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 18 ------------------ src/libvirt-domain.c | 4 ++-- src/qemu/qemu_driver.c | 9 ++++++--- src/qemu/qemu_monitor.h | 18 ++++++++++++++++-- src/qemu/qemu_monitor_json.c | 4 ++-- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 8c16598..bf4746a 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5241,24 +5241,6 @@ int virDomainGetMessages(virDomainPtr domain, char ***msgs, unsigned int flags); -/** - * virDomainDirtyRateStatus: - * - * Details on the cause of a dirty rate calculation status. - */ -typedef enum { - VIR_DOMAIN_DIRTYRATE_UNSTARTED = 0, /* the dirtyrate calculation has - not been started */ - VIR_DOMAIN_DIRTYRATE_MEASURING = 1, /* the dirtyrate calculation is - measuring */ - VIR_DOMAIN_DIRTYRATE_MEASURED = 2, /* the dirtyrate calculation is - completed */ - -# ifdef VIR_ENUM_SENTINELS - VIR_DOMAIN_DIRTYRATE_LAST -# endif -} virDomainDirtyRateStatus; - int virDomainStartDirtyRateCalc(virDomainPtr domain, int seconds, unsigned int flags); diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index b8a6f10..f24d072 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11947,8 +11947,8 @@ virConnectGetDomainCapabilities(virConnectPtr conn, * this format: * * "dirtyrate.calc_status" - the status of last memory dirty rate calculation, - * returned as int from virDomainDirtyRateStatus - * enum. + * either of these 3 'unstarted,measuring,measured' + * values returned. * "dirtyrate.calc_start_time" - the start time of last memory dirty rate * calculation as long long. * "dirtyrate.calc_period" - the period of last memory dirty rate calculation diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f262020..a22646c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18525,6 +18525,8 @@ qemuDomainGetStatsDirtyRateMon(virQEMUDriver *driver, return ret; } +VIR_ENUM_DECL(qemuMonitorDirtyRateStatus); + static int qemuDomainGetStatsDirtyRate(virQEMUDriver *driver, virDomainObj *dom, @@ -18539,8 +18541,9 @@ qemuDomainGetStatsDirtyRate(virQEMUDriver *driver, if (qemuDomainGetStatsDirtyRateMon(driver, dom, &info) < 0) return -1; - if (virTypedParamListAddInt(params, info.status, - "dirtyrate.calc_status") < 0) + if (virTypedParamListAddString(params, + qemuMonitorDirtyRateStatusTypeToString(info.status), + "dirtyrate.calc_status") < 0) return -1; if (virTypedParamListAddLLong(params, info.startTime, @@ -18551,7 +18554,7 @@ qemuDomainGetStatsDirtyRate(virQEMUDriver *driver, "dirtyrate.calc_period") < 0) return -1; - if ((info.status == VIR_DOMAIN_DIRTYRATE_MEASURED) && + if ((info.status == QEMU_MONITOR_DIRTYRATE_STATUS_MEASURED) && virTypedParamListAddLLong(params, info.dirtyRate, "dirtyrate.megabytes_per_second") < 0) return -1; diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 1d21183..817391c 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1538,10 +1538,24 @@ int qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, int seconds); +/** + * qemuMonitorDirtyRateStatus: + * + * Details on the cause of a dirty page rate calculation status. + */ +typedef enum { + QEMU_MONITOR_DIRTYRATE_STATUS_UNSTARTED = 0, /* the dirtyrate calculation has + not been started */ + QEMU_MONITOR_DIRTYRATE_STATUS_MEASURING, /* the dirtyrate calculation is + measuring */ + QEMU_MONITOR_DIRTYRATE_STATUS_MEASURED, /* the dirtyrate calculation is + completed */ + QEMU_MONITOR_DIRTYRATE_STATUS_LAST, +} qemuMonitorDirtyRateStatus; + typedef struct _qemuMonitorDirtyRateInfo qemuMonitorDirtyRateInfo; struct _qemuMonitorDirtyRateInfo { - int status; /* the status of last dirtyrate calculation, - one of virDomainDirtyRateStatus */ + qemuMonitorDirtyRateStatus status; /* the status of last dirtyrate calculation */ int calcTime; /* the period of dirtyrate calculation */ long long startTime; /* the start time of dirtyrate calculation */ long long dirtyRate; /* the dirtyrate in MiB/s */ diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 1de932f..b09ef12 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8764,7 +8764,7 @@ qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon, VIR_ENUM_DECL(qemuMonitorDirtyRateStatus); VIR_ENUM_IMPL(qemuMonitorDirtyRateStatus, - VIR_DOMAIN_DIRTYRATE_LAST, + QEMU_MONITOR_DIRTYRATE_STATUS_LAST, "unstarted", "measuring", "measured"); @@ -8792,7 +8792,7 @@ qemuMonitorJSONExtractDirtyRateInfo(virJSONValue *data, /* `query-dirty-rate` replies `dirty-rate` data only if the status of the latest * calculation is `measured`. */ - if ((info->status == VIR_DOMAIN_DIRTYRATE_MEASURED) && + if ((info->status == QEMU_MONITOR_DIRTYRATE_STATUS_MEASURED) && (virJSONValueObjectGetNumberLong(data, "dirty-rate", &info->dirtyRate) < 0)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("query-dirty-rate reply was missing 'dirty-rate' data")); -- 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 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a22646c..18775e7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20691,6 +20691,13 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, if (virDomainStartDirtyRateCalcEnsureACL(dom->conn, vm->def) < 0) goto cleanup; + 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 cleanup; + } + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -20702,7 +20709,6 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, VIR_DEBUG("Calculate dirty rate in next %d seconds", seconds); - priv = vm->privateData; qemuDomainObjEnterMonitor(driver, vm); ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds); -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> mode option of calc-dirty-rate command since qemu >=6.2.0. Introduce QEMU_CAPS_DIRTYRATE_MODE capability definition. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_6.2.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0.x86_64.xml | 1 + 6 files changed, 7 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 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 to get ready for adding mode parameter to qemuDomainStartDirtyRateCalc. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- include/libvirt/libvirt-domain.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index bf4746a..a474e83 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5241,6 +5241,19 @@ int virDomainGetMessages(virDomainPtr domain, char ***msgs, unsigned int flags); +/** + * 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); -- 1.8.3.1

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 | 3 ++- src/qemu/qemu_monitor.c | 5 +++-- src/qemu/qemu_monitor.h | 17 ++++++++++++++++- src/qemu/qemu_monitor_json.c | 16 ++++++++++++++-- src/qemu/qemu_monitor_json.h | 3 ++- 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 18775e7..2f4415e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20671,6 +20671,7 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, virQEMUDriver *driver = dom->conn->privateData; virDomainObj *vm = NULL; qemuDomainObjPrivate *priv; + qemuMonitorDirtyRateCalcMode mode = QEMU_MONITOR_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; int ret = -1; virCheckFlags(0, -1); @@ -20710,7 +20711,7 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, VIR_DEBUG("Calculate dirty rate in next %d seconds", seconds); 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 dc81e41..0ff938a 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4475,13 +4475,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 817391c..efdecba 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1534,9 +1534,24 @@ qemuMonitorTransactionBackup(virJSONValue *actions, const char *bitmap, qemuMonitorTransactionBackupSyncMode syncmode); +/** + * qemuMonitorDirtyRateCalcMode: + * + * Dirty page rate calculation mode used during measurement. + */ +typedef enum { + QEMU_MONITOR_DIRTYRATE_CALC_MODE_PAGE_SAMPLING = 0, + QEMU_MONITOR_DIRTYRATE_CALC_MODE_DIRTY_BITMAP, + QEMU_MONITOR_DIRTYRATE_CALC_MODE_DIRTY_RING, + QEMU_MONITOR_DIRTYRATE_CALC_MODE_LAST, +} qemuMonitorDirtyRateCalcMode; + +VIR_ENUM_DECL(qemuMonitorDirtyRateCalcMode); + int qemuMonitorStartDirtyRateCalc(qemuMonitor *mon, - int seconds); + int seconds, + qemuMonitorDirtyRateCalcMode mode); /** * qemuMonitorDirtyRateStatus: diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index b09ef12..93288ab 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8740,18 +8740,30 @@ qemuMonitorJSONGetCPUMigratable(qemuMonitor *mon, migratable); } +VIR_ENUM_IMPL(qemuMonitorDirtyRateCalcMode, + QEMU_MONITOR_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; + const char *modestr = NULL; + + if (mode != QEMU_MONITOR_DIRTYRATE_CALC_MODE_PAGE_SAMPLING) + modestr = qemuMonitorDirtyRateCalcModeTypeToString(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 eea3478..8e34f3b 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -853,7 +853,8 @@ qemuMonitorJSONGetCPUMigratable(qemuMonitor *mon, int qemuMonitorJSONStartDirtyRateCalc(qemuMonitor *mon, - int seconds); + int seconds, + qemuMonitorDirtyRateCalcMode mode); int qemuMonitorJSONQueryDirtyRate(qemuMonitor *mon, -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> Extend flags parameter of virDomainStartDirtyRateCalc as a superset of virDomainDirtyRateCalcFlags, parse the flags and handle it correspondingly in qemuDomainStartDirtyRateCalc. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- src/qemu/qemu_driver.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2f4415e..3ac5f01 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20674,7 +20674,9 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, qemuMonitorDirtyRateCalcMode mode = QEMU_MONITOR_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) { @@ -20699,6 +20701,25 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom, goto cleanup; } + if (flags & VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP) { + mode = QEMU_MONITOR_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 cleanup; + } + mode = QEMU_MONITOR_DIRTYRATE_CALC_MODE_DIRTY_RING; + } + + if (mode != QEMU_MONITOR_DIRTYRATE_CALC_MODE_PAGE_SAMPLING && + !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DIRTYRATE_MODE)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("QEMU does not support dirty page rate calculation mode.")); + goto cleanup; + } + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; -- 1.8.3.1

From: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> Extend domdirtyrate-calc virsh api with mode option, either of these three options "page-sampling,dirty-bitmap,dirty-ring" can be specified when calculating dirty page rate. Signed-off-by: Hyman Huang(黄勇) <huangy81@chinatelecom.cn> --- docs/manpages/virsh.rst | 7 +++++-- src/libvirt-domain.c | 12 +++++++++++- tools/virsh-completer-domain.c | 17 +++++++++++++++++ tools/virsh-completer-domain.h | 4 ++++ tools/virsh-domain.c | 42 +++++++++++++++++++++++++++++++++++++++++- tools/virsh-domain.h | 9 +++++++++ 6 files changed, 87 insertions(+), 4 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 429879d..00d21a1 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1717,13 +1717,16 @@ domdirtyrate-calc :: domdirtyrate-calc <domain> [--seconds <sec>] + --mode=[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* modes +are mutually exclusive and alternative when 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 f24d072..f70eff3 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -13313,7 +13313,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 @@ -13337,6 +13337,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-completer-domain.c b/tools/virsh-completer-domain.c index b4e744c..1c2df56 100644 --- a/tools/virsh-completer-domain.c +++ b/tools/virsh-completer-domain.c @@ -1150,3 +1150,20 @@ virshDomainNumatuneModeCompleter(vshControl *ctl G_GNUC_UNUSED, return ret; } + + +char ** +virshDomainDirtyRateCalcModeCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags) +{ + const char *modes[] = {"page-sampling", "dirty-bitmap", "dirty-ring", NULL}; + const char *mode = NULL; + + virCheckFlags(0, NULL); + + if (vshCommandOptStringQuiet(ctl, cmd, "mode", &mode) < 0) + return NULL; + + return virshCommaStringListComplete(mode, modes); +} diff --git a/tools/virsh-completer-domain.h b/tools/virsh-completer-domain.h index 94bb3b5..044c675 100644 --- a/tools/virsh-completer-domain.h +++ b/tools/virsh-completer-domain.h @@ -186,3 +186,7 @@ char ** virshDomainNumatuneModeCompleter(vshControl *ctl, const vshCmd *cmd, unsigned int flags); +char ** +virshDomainDirtyRateCalcModeCompleter(vshControl *ctl, + const vshCmd *cmd, + unsigned int flags); diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 4ff531f..1902eb9 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -14484,14 +14484,28 @@ 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 = "mode", + .type = VSH_OT_STRING, + .completer = virshDomainDirtyRateCalcModeCompleter, + .help = N_("dirty page rate calculation mode, either of these 3 options " + "'page-sampling,dirty-bitmap,dirty-ring' can be specified.") + }, {.name = NULL} }; +VIR_ENUM_IMPL(virshDomainDirtyRateCalcMode, + VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_LAST, + "page-sampling", + "dirty-bitmap", + "dirty-ring"); + static bool cmdDomDirtyRateCalc(vshControl *ctl, const vshCmd *cmd) { g_autoptr(virshDomain) dom = NULL; int seconds = 1; /* the default value is 1 */ + const char *modestr = NULL; + unsigned int flags = 0; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) return false; @@ -14499,7 +14513,33 @@ cmdDomDirtyRateCalc(vshControl *ctl, const vshCmd *cmd) if (vshCommandOptInt(ctl, cmd, "seconds", &seconds) < 0) return false; - if (virDomainStartDirtyRateCalc(dom, seconds, 0) < 0) + if (vshCommandOptStringReq(ctl, cmd, "mode", &modestr) < 0) + return false; + + if (modestr) { + int mode = virshDomainDirtyRateCalcModeTypeFromString(modestr); + + if (mode < 0) { + vshError(ctl, _("Unknown calculation mode '%s'"), modestr); + return false; + } + + switch ((virshDomainDirtyRateCalcMode) mode) { + case VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING: + flags |= VIR_DOMAIN_DIRTYRATE_MODE_PAGE_SAMPLING; + break; + case VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_BITMAP: + flags |= VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_BITMAP;; + break; + case VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_RING: + flags |= VIR_DOMAIN_DIRTYRATE_MODE_DIRTY_RING;; + break; + case VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_LAST: + break; + } + } + + if (virDomainStartDirtyRateCalc(dom, seconds, flags) < 0) return false; vshPrintExtra(ctl, _("Start to calculate domain's memory " diff --git a/tools/virsh-domain.h b/tools/virsh-domain.h index cf5ce28..6a94438 100644 --- a/tools/virsh-domain.h +++ b/tools/virsh-domain.h @@ -46,6 +46,15 @@ typedef enum { VIR_ENUM_DECL(virshDomainInterfaceSourceMode); +typedef enum { + VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_PAGE_SAMPLING, + VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_BITMAP, + VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_DIRTY_RING, + VIRSH_DOMAIN_DIRTYRATE_CALC_MODE_LAST, +} virshDomainDirtyRateCalcMode; + +VIR_ENUM_DECL(virshDomainDirtyRateCalcMode); + extern const vshCmdDef domManagementCmds[]; VIR_ENUM_DECL(virshDomainProcessSignal); -- 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 | 6 +++++ src/qemu/qemu_driver.c | 22 +++++++++++++++--- src/qemu/qemu_monitor.h | 10 +++++++++ src/qemu/qemu_monitor_json.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index f70eff3..1fcbfc5 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11956,6 +11956,12 @@ 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, either + * of these 3 'page-sampling,dirty-bitmap,dirty-ring' + * values returned. + * "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 3ac5f01..7ce7936 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18554,11 +18554,27 @@ qemuDomainGetStatsDirtyRate(virQEMUDriver *driver, "dirtyrate.calc_period") < 0) return -1; - if ((info.status == QEMU_MONITOR_DIRTYRATE_STATUS_MEASURED) && - virTypedParamListAddLLong(params, info.dirtyRate, - "dirtyrate.megabytes_per_second") < 0) + if (virTypedParamListAddString(params, + qemuMonitorDirtyRateCalcModeTypeToString(info.mode), + "dirtyrate.calc_mode") < 0) return -1; + if (info.status == QEMU_MONITOR_DIRTYRATE_STATUS_MEASURED) { + if (virTypedParamListAddLLong(params, info.dirtyRate, + "dirtyrate.megabytes_per_second") < 0) + return -1; + + if (info.mode == QEMU_MONITOR_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 efdecba..8008f40 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1568,12 +1568,22 @@ typedef enum { QEMU_MONITOR_DIRTYRATE_STATUS_LAST, } qemuMonitorDirtyRateStatus; +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 { qemuMonitorDirtyRateStatus status; /* the status of last dirtyrate calculation */ 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 93288ab..7ee0026 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8782,11 +8782,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", @@ -8823,6 +8857,25 @@ qemuMonitorJSONExtractDirtyRateInfo(virJSONValue *data, return -1; } + if ((modestr = virJSONValueObjectGetString(data, "mode"))) { + if ((mode = qemuMonitorDirtyRateCalcModeTypeFromString(modestr)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown dirty page rate calculation mode: %s"), modestr); + return -1; + } + info->mode = mode; + } else { + info->mode = QEMU_MONITOR_DIRTYRATE_CALC_MODE_PAGE_SAMPLING; + } + + if ((rates = virJSONValueObjectGetArray(data, "vcpu-dirty-rate"))) { + if (qemuMonitorJSONExtractVcpuDirtyRate(rates, info) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-dirty-rate parsing 'vcpu-dirty-rate' in failure")); + return -1; + } + } + return 0; } -- 1.8.3.1
participants (1)
-
huangy81@chinatelecom.cn