From 81e3aa297594fd6ffad5326a2b899e4321f36a61 Mon Sep 17 00:00:00 2001 From: yezengruan Date: Thu, 3 Nov 2022 20:05:39 +0800 Subject: [PATCH] libvirt: support migration dirtyrate Signed-off-by: yezengruan --- libvirt.spec | 12 +- ...ate-Extend-dirtyrate-statistics-for-.patch | 133 ++++++++++++ ...ate-Implement-qemuDomainStartDirtyRa.patch | 178 ++++++++++++++++ ...ate-Implement-qemuMonitorQueryDirtyR.patch | 168 +++++++++++++++ ...ate-Introduce-command-virsh-domstats.patch | 97 +++++++++ ...ate-Introduce-domdirtyrate-calc-virs.patch | 129 ++++++++++++ ...ate-Introduce-virDomainDirtyRateStat.patch | 52 +++++ ...ate-Introduce-virDomainStartDirtyRat.patch | 192 ++++++++++++++++++ 8 files changed, 960 insertions(+), 1 deletion(-) create mode 100644 migration-dirtyrate-Extend-dirtyrate-statistics-for-.patch create mode 100644 migration-dirtyrate-Implement-qemuDomainStartDirtyRa.patch create mode 100644 migration-dirtyrate-Implement-qemuMonitorQueryDirtyR.patch create mode 100644 migration-dirtyrate-Introduce-command-virsh-domstats.patch create mode 100644 migration-dirtyrate-Introduce-domdirtyrate-calc-virs.patch create mode 100644 migration-dirtyrate-Introduce-virDomainDirtyRateStat.patch create mode 100644 migration-dirtyrate-Introduce-virDomainStartDirtyRat.patch diff --git a/libvirt.spec b/libvirt.spec index b5331f0..0a8b835 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -101,7 +101,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 6.2.0 -Release: 43 +Release: 44 License: LGPLv2+ URL: https://libvirt.org/ @@ -360,6 +360,13 @@ Patch0247: util-fix-cache-invalidation-of-swtpm-capabilities.patch Patch0248: virnettlscontext-Drop-gnutls_dh_set_prime_bits.patch Patch0249: virnettlscontext-Don-t-pass-static-key-length-to-gnu.patch Patch0250: rpc-Fix-memory-leak-of-fds.patch +Patch0251: migration-dirtyrate-Introduce-virDomainStartDirtyRat.patch +Patch0252: migration-dirtyrate-Implement-qemuDomainStartDirtyRa.patch +Patch0253: migration-dirtyrate-Introduce-domdirtyrate-calc-virs.patch +Patch0254: migration-dirtyrate-Introduce-virDomainDirtyRateStat.patch +Patch0255: migration-dirtyrate-Implement-qemuMonitorQueryDirtyR.patch +Patch0256: migration-dirtyrate-Extend-dirtyrate-statistics-for-.patch +Patch0257: migration-dirtyrate-Introduce-command-virsh-domstats.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -2094,6 +2101,9 @@ exit 0 %changelog +* Thu Nov 03 2022 yezengruan - 6.2.0-44 +- libvirt: support migration dirtyrate + * Tue Oct 11 2022 wengyu - 6.2.0-43 - libvirt: Synchronize upstream patches according to issue I5OLYY diff --git a/migration-dirtyrate-Extend-dirtyrate-statistics-for-.patch b/migration-dirtyrate-Extend-dirtyrate-statistics-for-.patch new file mode 100644 index 0000000..bf5156d --- /dev/null +++ b/migration-dirtyrate-Extend-dirtyrate-statistics-for-.patch @@ -0,0 +1,133 @@ +From d38fa8e57331b666839b6d9cc3744058f8de8093 Mon Sep 17 00:00:00 2001 +From: Hao Wang +Date: Tue, 16 Mar 2021 20:32:50 +0800 +Subject: [PATCH 6/7] migration/dirtyrate: Extend dirtyrate statistics for + domGetStats +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Extend dirtyrate statistics for domGetStats to display the information +of a domain's memory dirty rate produced by domainStartDirtyRateCalc. + +cherry-pick from fee42ea12044d1414c1a5c0b0dca30091f42e65d + +Signed-off-by: Hao Wang +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Michal Privoznik +--- + include/libvirt/libvirt-domain.h | 1 + + src/libvirt-domain.c | 15 ++++++++++ + src/qemu/qemu_driver.c | 51 ++++++++++++++++++++++++++++++++ + 3 files changed, 67 insertions(+) + +diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h +index 01dc64f4f4..e1954ae663 100644 +--- a/include/libvirt/libvirt-domain.h ++++ b/include/libvirt/libvirt-domain.h +@@ -2167,6 +2167,7 @@ typedef enum { + VIR_DOMAIN_STATS_PERF = (1 << 6), /* return domain perf event info */ + VIR_DOMAIN_STATS_IOTHREAD = (1 << 7), /* return iothread poll info */ + VIR_DOMAIN_STATS_MEMORY = (1 << 8), /* return domain memory info */ ++ VIR_DOMAIN_STATS_DIRTYRATE = (1 << 9), /* return domain dirty rate info */ + } virDomainStatsTypes; + + typedef enum { +diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c +index 974a5a5f36..6a37ea85b7 100644 +--- a/src/libvirt-domain.c ++++ b/src/libvirt-domain.c +@@ -11683,6 +11683,21 @@ virConnectGetDomainCapabilities(virConnectPtr conn, + * bytes consumed by @vcpus that passing through all + * memory controllers, either local or remote controller. + * ++ * VIR_DOMAIN_STATS_DIRTYRATE: ++ * Return memory dirty rate information. The typed parameter keys are in ++ * this format: ++ * ++ * "dirtyrate.calc_status" - the status of last memory dirty rate calculation, ++ * returned as int from virDomainDirtyRateStatus ++ * enum. ++ * "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 ++ * as int. ++ * "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. ++ * + * 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 + * applicable for the current state of the guest domain, or their retrieval +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index b0a4905279..5e9af6399d 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -21734,6 +21734,56 @@ qemuDomainGetStatsPerf(virQEMUDriverPtr driver G_GNUC_UNUSED, + return 0; + } + ++static int ++qemuDomainGetStatsDirtyRateMon(virQEMUDriverPtr driver, ++ virDomainObjPtr vm, ++ qemuMonitorDirtyRateInfoPtr info) ++{ ++ qemuDomainObjPrivatePtr priv = vm->privateData; ++ int ret; ++ ++ qemuDomainObjEnterMonitor(driver, vm); ++ ret = qemuMonitorQueryDirtyRate(priv->mon, info); ++ if (qemuDomainObjExitMonitor(driver, vm) < 0) ++ ret = -1; ++ ++ return ret; ++} ++ ++static int ++qemuDomainGetStatsDirtyRate(virQEMUDriverPtr driver, ++ virDomainObjPtr dom, ++ virTypedParamListPtr params, ++ unsigned int privflags) ++{ ++ qemuMonitorDirtyRateInfo info; ++ ++ if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom)) ++ return 0; ++ ++ if (qemuDomainGetStatsDirtyRateMon(driver, dom, &info) < 0) ++ return -1; ++ ++ if (virTypedParamListAddInt(params, info.status, ++ "dirtyrate.calc_status") < 0) ++ return -1; ++ ++ if (virTypedParamListAddLLong(params, info.startTime, ++ "dirtyrate.calc_start_time") < 0) ++ return -1; ++ ++ if (virTypedParamListAddInt(params, info.calcTime, ++ "dirtyrate.calc_period") < 0) ++ return -1; ++ ++ if ((info.status == VIR_DOMAIN_DIRTYRATE_MEASURED) && ++ virTypedParamListAddLLong(params, info.dirtyRate, ++ "dirtyrate.megabytes_per_second") < 0) ++ return -1; ++ ++ return 0; ++} ++ + typedef int + (*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver, + virDomainObjPtr dom, +@@ -21756,6 +21806,7 @@ static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = { + { qemuDomainGetStatsPerf, VIR_DOMAIN_STATS_PERF, false }, + { qemuDomainGetStatsIOThread, VIR_DOMAIN_STATS_IOTHREAD, true }, + { qemuDomainGetStatsMemory, VIR_DOMAIN_STATS_MEMORY, false }, ++ { qemuDomainGetStatsDirtyRate, VIR_DOMAIN_STATS_DIRTYRATE, true }, + { NULL, 0, false } + }; + +-- +2.27.0 + diff --git a/migration-dirtyrate-Implement-qemuDomainStartDirtyRa.patch b/migration-dirtyrate-Implement-qemuDomainStartDirtyRa.patch new file mode 100644 index 0000000..174a174 --- /dev/null +++ b/migration-dirtyrate-Implement-qemuDomainStartDirtyRa.patch @@ -0,0 +1,178 @@ +From d6dd8dba23726495026b721da0835f7916000f94 Mon Sep 17 00:00:00 2001 +From: Hao Wang +Date: Tue, 16 Mar 2021 20:32:46 +0800 +Subject: [PATCH 2/7] migration/dirtyrate: Implement + qemuDomainStartDirtyRateCalc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement qemuDomainStartDirtyRateCalc which calculates domain's memory +dirty rate calling qmp "calc-dirty-rate". + +cherry-pick from fbe99823e2a1b30e770620b0b51930e15c88de00 + +Signed-off-by: Hao Wang +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Michal Privoznik +--- + src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++ + src/qemu/qemu_monitor.c | 12 ++++++++ + src/qemu/qemu_monitor.h | 4 +++ + src/qemu/qemu_monitor_json.c | 21 +++++++++++++ + src/qemu/qemu_monitor_json.h | 4 +++ + 5 files changed, 100 insertions(+) + +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index e7166e4af3..b0a4905279 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -23298,6 +23298,64 @@ qemuDomainHotpatchManage(virDomainPtr domain, + return ret; + } + ++#define MIN_DIRTYRATE_CALC_PERIOD 1 /* supported min dirtyrate calculating time: 1s */ ++#define MAX_DIRTYRATE_CALC_PERIOD 60 /* supported max dirtyrate calculating time: 60s */ ++ ++static int ++qemuDomainStartDirtyRateCalc(virDomainPtr dom, ++ int seconds, ++ unsigned int flags) ++{ ++ virQEMUDriverPtr driver = dom->conn->privateData; ++ virDomainObjPtr vm; ++ qemuDomainObjPrivatePtr priv; ++ int ret = -1; ++ ++ virCheckFlags(0, -1); ++ ++ if (seconds < MIN_DIRTYRATE_CALC_PERIOD || ++ seconds > MAX_DIRTYRATE_CALC_PERIOD) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("seconds=%d is invalid, please choose value within [%d, %d]."), ++ seconds, ++ MIN_DIRTYRATE_CALC_PERIOD, ++ MAX_DIRTYRATE_CALC_PERIOD); ++ return -1; ++ } ++ ++ if (!(vm = qemuDomainObjFromDomain(dom))) ++ return -1; ++ ++ if (virDomainStartDirtyRateCalcEnsureACL(dom->conn, vm->def) < 0) ++ goto cleanup; ++ ++ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) ++ goto cleanup; ++ ++ if (!virDomainObjIsActive(vm)) { ++ virReportError(VIR_ERR_OPERATION_INVALID, ++ "%s", _("domain is not running")); ++ goto endjob; ++ } ++ ++ VIR_DEBUG("Calculate dirty rate in next %d seconds", seconds); ++ ++ priv = vm->privateData; ++ qemuDomainObjEnterMonitor(driver, vm); ++ ret = qemuMonitorStartDirtyRateCalc(priv->mon, seconds); ++ ++ if (qemuDomainObjExitMonitor(driver, vm) < 0) ++ ret = -1; ++ ++ endjob: ++ qemuDomainObjEndJob(driver, vm); ++ ++ cleanup: ++ virDomainObjEndAPI(&vm); ++ return ret; ++} ++ ++ + static virHypervisorDriver qemuHypervisorDriver = { + .name = QEMU_DRIVER_NAME, + .connectURIProbe = qemuConnectURIProbe, +@@ -23538,6 +23596,7 @@ static virHypervisorDriver qemuHypervisorDriver = { + .domainBackupBegin = qemuDomainBackupBegin, /* 6.0.0 */ + .domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 6.0.0 */ + .domainHotpatchManage = qemuDomainHotpatchManage, /* 6.2.0 */ ++ .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 6.2.0 */ + }; + + +diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c +index ec79fa6368..cdfe5fbed9 100644 +--- a/src/qemu/qemu_monitor.c ++++ b/src/qemu/qemu_monitor.c +@@ -4615,3 +4615,15 @@ qemuMonitorTransactionBackup(virJSONValuePtr actions, + return qemuMonitorJSONTransactionBackup(actions, device, jobname, target, + bitmap, syncmode); + } ++ ++ ++int ++qemuMonitorStartDirtyRateCalc(qemuMonitorPtr mon, ++ int seconds) ++{ ++ VIR_DEBUG("seconds=%d", seconds); ++ ++ QEMU_CHECK_MONITOR(mon); ++ ++ return qemuMonitorJSONStartDirtyRateCalc(mon, seconds); ++} +diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h +index 73c8af9e78..7b859155c3 100644 +--- a/src/qemu/qemu_monitor.h ++++ b/src/qemu/qemu_monitor.h +@@ -1425,3 +1425,7 @@ qemuMonitorTransactionBackup(virJSONValuePtr actions, + const char *target, + const char *bitmap, + qemuMonitorTransactionBackupSyncMode syncmode); ++ ++int ++qemuMonitorStartDirtyRateCalc(qemuMonitorPtr mon, ++ int seconds); +diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c +index cc6644c9c3..fad9a2c233 100644 +--- a/src/qemu/qemu_monitor_json.c ++++ b/src/qemu/qemu_monitor_json.c +@@ -9374,3 +9374,24 @@ qemuMonitorJSONGetJobInfo(qemuMonitorPtr mon, + + return 0; + } ++ ++int ++qemuMonitorJSONStartDirtyRateCalc(qemuMonitorPtr mon, ++ int seconds) ++{ ++ g_autoptr(virJSONValue) cmd = NULL; ++ g_autoptr(virJSONValue) reply = NULL; ++ ++ if (!(cmd = qemuMonitorJSONMakeCommand("calc-dirty-rate", ++ "i:calc-time", seconds, ++ NULL))) ++ return -1; ++ ++ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) ++ return -1; ++ ++ if (qemuMonitorJSONCheckError(cmd, reply) < 0) ++ return -1; ++ ++ return 0; ++} +diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h +index 2c0e3ec07a..048e7c267c 100644 +--- a/src/qemu/qemu_monitor_json.h ++++ b/src/qemu/qemu_monitor_json.h +@@ -691,3 +691,7 @@ int qemuMonitorJSONSetDBusVMStateIdList(qemuMonitorPtr mon, + const char *vmstatepath, + const char **list) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); ++ ++int ++qemuMonitorJSONStartDirtyRateCalc(qemuMonitorPtr mon, ++ int seconds); +-- +2.27.0 + diff --git a/migration-dirtyrate-Implement-qemuMonitorQueryDirtyR.patch b/migration-dirtyrate-Implement-qemuMonitorQueryDirtyR.patch new file mode 100644 index 0000000..5f02773 --- /dev/null +++ b/migration-dirtyrate-Implement-qemuMonitorQueryDirtyR.patch @@ -0,0 +1,168 @@ +From c89672b2f41e1905b3b6e4fd0e37b709f629c422 Mon Sep 17 00:00:00 2001 +From: Hao Wang +Date: Tue, 16 Mar 2021 20:32:49 +0800 +Subject: [PATCH 5/7] migration/dirtyrate: Implement qemuMonitorQueryDirtyRate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement qemuMonitorQueryDirtyRate which query domain's memory +dirty rate calling qmp "query-dirty-rate". + +cherry-pick from 4ae60b1cafec45209198d5ef2e1300474d63f327 + +Signed-off-by: Hao Wang +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Michal Privoznik +--- + src/qemu/qemu_monitor.c | 12 ++++++ + src/qemu/qemu_monitor.h | 15 +++++++ + src/qemu/qemu_monitor_json.c | 79 ++++++++++++++++++++++++++++++++++++ + src/qemu/qemu_monitor_json.h | 4 ++ + 4 files changed, 110 insertions(+) + +diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c +index cdfe5fbed9..704c45d77d 100644 +--- a/src/qemu/qemu_monitor.c ++++ b/src/qemu/qemu_monitor.c +@@ -4627,3 +4627,15 @@ qemuMonitorStartDirtyRateCalc(qemuMonitorPtr mon, + + return qemuMonitorJSONStartDirtyRateCalc(mon, seconds); + } ++ ++ ++int ++qemuMonitorQueryDirtyRate(qemuMonitorPtr mon, ++ qemuMonitorDirtyRateInfoPtr info) ++{ ++ VIR_DEBUG("info=%p", info); ++ ++ QEMU_CHECK_MONITOR(mon); ++ ++ return qemuMonitorJSONQueryDirtyRate(mon, info); ++} +diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h +index 7b859155c3..9c797d5ff5 100644 +--- a/src/qemu/qemu_monitor.h ++++ b/src/qemu/qemu_monitor.h +@@ -1429,3 +1429,18 @@ qemuMonitorTransactionBackup(virJSONValuePtr actions, + int + qemuMonitorStartDirtyRateCalc(qemuMonitorPtr mon, + int seconds); ++ ++typedef struct _qemuMonitorDirtyRateInfo qemuMonitorDirtyRateInfo; ++typedef qemuMonitorDirtyRateInfo *qemuMonitorDirtyRateInfoPtr; ++ ++struct _qemuMonitorDirtyRateInfo { ++ int status; /* the status of last dirtyrate calculation, ++ one of virDomainDirtyRateStatus */ ++ int calcTime; /* the period of dirtyrate calculation */ ++ long long startTime; /* the start time of dirtyrate calculation */ ++ long long dirtyRate; /* the dirtyrate in MiB/s */ ++}; ++ ++int ++qemuMonitorQueryDirtyRate(qemuMonitorPtr mon, ++ qemuMonitorDirtyRateInfoPtr info); +diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c +index fad9a2c233..3ec7fc84f5 100644 +--- a/src/qemu/qemu_monitor_json.c ++++ b/src/qemu/qemu_monitor_json.c +@@ -9395,3 +9395,82 @@ qemuMonitorJSONStartDirtyRateCalc(qemuMonitorPtr mon, + + return 0; + } ++ ++VIR_ENUM_DECL(qemuMonitorDirtyRateStatus); ++VIR_ENUM_IMPL(qemuMonitorDirtyRateStatus, ++ VIR_DOMAIN_DIRTYRATE_LAST, ++ "unstarted", ++ "measuring", ++ "measured"); ++ ++static int ++qemuMonitorJSONExtractDirtyRateInfo(virJSONValuePtr data, ++ qemuMonitorDirtyRateInfoPtr info) ++{ ++ const char *statusstr; ++ int status; ++ ++ if (!(statusstr = virJSONValueObjectGetString(data, "status"))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("query-dirty-rate reply was missing 'status' data")); ++ return -1; ++ } ++ ++ if ((status = qemuMonitorDirtyRateStatusTypeFromString(statusstr)) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown dirty rate status: %s"), statusstr); ++ return -1; ++ } ++ info->status = status; ++ ++ /* `query-dirty-rate` replies `dirty-rate` data only if the status of the latest ++ * calculation is `measured`. ++ */ ++ if ((info->status == VIR_DOMAIN_DIRTYRATE_MEASURED) && ++ (virJSONValueObjectGetNumberLong(data, "dirty-rate", &info->dirtyRate) < 0)) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("query-dirty-rate reply was missing 'dirty-rate' data")); ++ return -1; ++ } ++ ++ if (virJSONValueObjectGetNumberLong(data, "start-time", &info->startTime) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("query-dirty-rate reply was missing 'start-time' data")); ++ return -1; ++ } ++ ++ if (virJSONValueObjectGetNumberInt(data, "calc-time", &info->calcTime) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("query-dirty-rate reply was missing 'calc-time' data")); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++int ++qemuMonitorJSONQueryDirtyRate(qemuMonitorPtr mon, ++ qemuMonitorDirtyRateInfoPtr info) ++{ ++ g_autoptr(virJSONValue) cmd = NULL; ++ g_autoptr(virJSONValue) reply = NULL; ++ virJSONValuePtr data = NULL; ++ ++ if (!(cmd = qemuMonitorJSONMakeCommand("query-dirty-rate", NULL))) ++ return -1; ++ ++ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) ++ return -1; ++ ++ if (qemuMonitorJSONCheckError(cmd, reply) < 0) ++ return -1; ++ ++ if (!(data = virJSONValueObjectGetObject(reply, "return"))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("query-dirty-rate reply was missing 'return' data")); ++ return -1; ++ } ++ ++ return qemuMonitorJSONExtractDirtyRateInfo(data, info); ++} +diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h +index 048e7c267c..531ff59a00 100644 +--- a/src/qemu/qemu_monitor_json.h ++++ b/src/qemu/qemu_monitor_json.h +@@ -695,3 +695,7 @@ int qemuMonitorJSONSetDBusVMStateIdList(qemuMonitorPtr mon, + int + qemuMonitorJSONStartDirtyRateCalc(qemuMonitorPtr mon, + int seconds); ++ ++int ++qemuMonitorJSONQueryDirtyRate(qemuMonitorPtr mon, ++ qemuMonitorDirtyRateInfoPtr info); +-- +2.27.0 + diff --git a/migration-dirtyrate-Introduce-command-virsh-domstats.patch b/migration-dirtyrate-Introduce-command-virsh-domstats.patch new file mode 100644 index 0000000..afc275d --- /dev/null +++ b/migration-dirtyrate-Introduce-command-virsh-domstats.patch @@ -0,0 +1,97 @@ +From a914cfe2abd42395cc1f4cab9c435d82fdd697cb Mon Sep 17 00:00:00 2001 +From: Hao Wang +Date: Tue, 16 Mar 2021 20:32:51 +0800 +Subject: [PATCH 7/7] migration/dirtyrate: Introduce command 'virsh domstats + --dirtyrate' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce command 'virsh domstats --dirtyrate' for reporting memory +dirty rate information. The info is listed as: + +Domain: 'vm0' + dirtyrate.calc_status=2 + dirtyrate.calc_start_time=1534523 + dirtyrate.calc_period=1 + dirtyrate.megabytes_per_second=5 + +cherry-pick from 5be6decbb131a2139161bf8ec4575f45997e31ee + +Signed-off-by: Hao Wang +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Michal Privoznik +--- + docs/manpages/virsh.rst | 16 ++++++++++++++-- + tools/virsh-domain-monitor.c | 7 +++++++ + 2 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst +index b44e8f9301..3d4fadc041 100644 +--- a/docs/manpages/virsh.rst ++++ b/docs/manpages/virsh.rst +@@ -2208,7 +2208,7 @@ domstats + + domstats [--raw] [--enforce] [--backing] [--nowait] [--state] + [--cpu-total] [--balloon] [--vcpu] [--interface] +- [--block] [--perf] [--iothread] [--memory] ++ [--block] [--perf] [--iothread] [--memory] [--dirtyrate] + [[--list-active] [--list-inactive] + [--list-persistent] [--list-transient] [--list-running]y + [--list-paused] [--list-shutoff] [--list-other]] | [domain ...] +@@ -2227,7 +2227,8 @@ behavior use the *--raw* flag. + The individual statistics groups are selectable via specific flags. By + default all supported statistics groups are returned. Supported + statistics groups flags are: *--state*, *--cpu-total*, *--balloon*, +-*--vcpu*, *--interface*, *--block*, *--perf*, *--iothread*, *--memory*. ++*--vcpu*, *--interface*, *--block*, *--perf*, *--iothread*, *--memory*, ++*--dirtyrate*. + + Note that - depending on the hypervisor type and version or the domain state + - not all of the following statistics may be returned. +@@ -2411,6 +2412,17 @@ not available for statistical purposes. + bytes consumed by @vcpus that passing through all memory controllers, either + local or remote controller. + ++*--dirtyrate* returns: ++ ++* ``dirtyrate.calc_status`` - the status of last memory dirty rate ++ calculation, returned as number from virDomainDirtyRateStatus enum. ++* ``dirtyrate.calc_start_time`` - the start time of last memory dirty ++ rate calculation. ++* ``dirtyrate.calc_period`` - the period of last memory dirty rate ++ calculation. ++* ``dirtyrate.megabytes_per_second`` - the calculated memory dirty ++ rate in MiB/s. ++ + + Selecting a specific statistics groups doesn't guarantee that the + daemon supports the selected group of stats. Flag *--enforce* +diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c +index 74ff369597..e692fefa2c 100644 +--- a/tools/virsh-domain-monitor.c ++++ b/tools/virsh-domain-monitor.c +@@ -2130,6 +2130,10 @@ static const vshCmdOptDef opts_domstats[] = { + .type = VSH_OT_BOOL, + .help = N_("report domain memory usage"), + }, ++ {.name = "dirtyrate", ++ .type = VSH_OT_BOOL, ++ .help = N_("report domain dirty rate information"), ++ }, + {.name = "list-active", + .type = VSH_OT_BOOL, + .help = N_("list only active domains"), +@@ -2249,6 +2253,9 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd) + if (vshCommandOptBool(cmd, "memory")) + stats |= VIR_DOMAIN_STATS_MEMORY; + ++ if (vshCommandOptBool(cmd, "dirtyrate")) ++ stats |= VIR_DOMAIN_STATS_DIRTYRATE; ++ + if (vshCommandOptBool(cmd, "list-active")) + flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE; + +-- +2.27.0 + diff --git a/migration-dirtyrate-Introduce-domdirtyrate-calc-virs.patch b/migration-dirtyrate-Introduce-domdirtyrate-calc-virs.patch new file mode 100644 index 0000000..51b87ba --- /dev/null +++ b/migration-dirtyrate-Introduce-domdirtyrate-calc-virs.patch @@ -0,0 +1,129 @@ +From f254d3fe1e7b50c850c634adf554e4e384a4abad Mon Sep 17 00:00:00 2001 +From: Hao Wang +Date: Tue, 16 Mar 2021 20:32:47 +0800 +Subject: [PATCH 3/7] migration/dirtyrate: Introduce domdirtyrate-calc virsh + api +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce domdirtyrate-calc virsh api to start calculating domain's +memory dirty rate: + # virsh domdirtyrate-calc [--seconds ] + +cherry-pick from a2ae2dad062e8b23efac132488ce6aaea388de51 + +Signed-off-by: Hao Wang +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Michal Privoznik +--- + docs/manpages/virsh.rst | 17 ++++++++++++ + tools/virsh-domain.c | 58 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 75 insertions(+) + +diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst +index dc404ddfe8..b44e8f9301 100644 +--- a/docs/manpages/virsh.rst ++++ b/docs/manpages/virsh.rst +@@ -1696,6 +1696,23 @@ states other than "ok" or "error" the command also prints number of + seconds elapsed since the control interface entered its current state. + + ++domdirtyrate-calc ++----------------- ++ ++**Syntax:** ++ ++:: ++ ++ domdirtyrate-calc [--seconds ] ++ ++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'. ++ ++ + domdisplay + ---------- + +diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c +index b5375ebd3e..0d42496898 100644 +--- a/tools/virsh-domain.c ++++ b/tools/virsh-domain.c +@@ -14399,6 +14399,58 @@ cmdHotpatch(vshControl *ctl, + return true; + } + ++/* ++ * "domdirtyrate" command ++ */ ++static const vshCmdInfo info_domdirtyrate_calc[] = { ++ {.name = "help", ++ .data = N_("Calculate a vm's memory dirty rate") ++ }, ++ {.name = "desc", ++ .data = N_("Calculate memory dirty rate of a domain in order to " ++ "decide whether it's proper to be migrated out or not.\n" ++ "The calculated dirty rate information is available by " ++ "calling 'domstats --dirtyrate'.") ++ }, ++ {.name = NULL} ++}; ++ ++static const vshCmdOptDef opts_domdirtyrate_calc[] = { ++ VIRSH_COMMON_OPT_DOMAIN_FULL(0), ++ {.name = "seconds", ++ .type = VSH_OT_INT, ++ .help = N_("calculate memory dirty rate within specified seconds, " ++ "the supported value range from 1 to 60, default to 1.") ++ }, ++ {.name = NULL} ++}; ++ ++static bool ++cmdDomDirtyRateCalc(vshControl *ctl, const vshCmd *cmd) ++{ ++ virDomainPtr dom = NULL; ++ int seconds = 1; /* the default value is 1 */ ++ bool ret = false; ++ ++ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) ++ return false; ++ ++ if (vshCommandOptInt(ctl, cmd, "seconds", &seconds) < 0) ++ goto cleanup; ++ ++ if (virDomainStartDirtyRateCalc(dom, seconds, 0) < 0) ++ goto cleanup; ++ ++ vshPrintExtra(ctl, _("Start to calculate domain's memory " ++ "dirty rate successfully.\n")); ++ ret = true; ++ ++ cleanup: ++ virshDomainFree(dom); ++ return ret; ++} ++ ++ + const vshCmdDef domManagementCmds[] = { + {.name = "attach-device", + .handler = cmdAttachDevice, +@@ -15032,5 +15084,11 @@ const vshCmdDef domManagementCmds[] = { + .info = info_hotpatch, + .flags = 0 + }, ++ {.name = "domdirtyrate-calc", ++ .handler = cmdDomDirtyRateCalc, ++ .opts = opts_domdirtyrate_calc, ++ .info = info_domdirtyrate_calc, ++ .flags = 0 ++ }, + {.name = NULL} + }; +-- +2.27.0 + diff --git a/migration-dirtyrate-Introduce-virDomainDirtyRateStat.patch b/migration-dirtyrate-Introduce-virDomainDirtyRateStat.patch new file mode 100644 index 0000000..efeb231 --- /dev/null +++ b/migration-dirtyrate-Introduce-virDomainDirtyRateStat.patch @@ -0,0 +1,52 @@ +From 752ee833cda682db3cb0a38b094f3a2ec1317486 Mon Sep 17 00:00:00 2001 +From: Hao Wang +Date: Tue, 16 Mar 2021 20:32:48 +0800 +Subject: [PATCH 4/7] migration/dirtyrate: Introduce virDomainDirtyRateStatus + enum +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce virDomainDirtyRateStatus enum. + +cherry-pick from a0c7f61f37c087dcc1fadfba9f5308b0bcb5784a + +Signed-off-by: Hao Wang +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Michal Privoznik +--- + include/libvirt/libvirt-domain.h | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h +index 24df273045..01dc64f4f4 100644 +--- a/include/libvirt/libvirt-domain.h ++++ b/include/libvirt/libvirt-domain.h +@@ -5011,6 +5011,24 @@ virDomainHotpatchManage(virDomainPtr domain, + const char *id, + 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); +-- +2.27.0 + diff --git a/migration-dirtyrate-Introduce-virDomainStartDirtyRat.patch b/migration-dirtyrate-Introduce-virDomainStartDirtyRat.patch new file mode 100644 index 0000000..26ab600 --- /dev/null +++ b/migration-dirtyrate-Introduce-virDomainStartDirtyRat.patch @@ -0,0 +1,192 @@ +From cd1852cbccb7a9b5055bcc11d1ed3b4b26c4d213 Mon Sep 17 00:00:00 2001 +From: Hao Wang +Date: Tue, 16 Mar 2021 20:32:45 +0800 +Subject: [PATCH 1/7] migration/dirtyrate: Introduce + virDomainStartDirtyRateCalc API +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce virDomainStartDirtyRateCalc API for start calculation of +a domain's memory dirty rate with a specified time. + +cherry-pick from df5c5c3e60e5a3b8e9b827cc51984f055ba1ce01 + +Signed-off-by: Hao Wang +Signed-off-by: Hyman Huang(黄勇) +Reviewed-by: Michal Privoznik +--- + include/libvirt/libvirt-domain.h | 4 +++ + src/driver-hypervisor.h | 6 +++++ + src/libvirt-domain.c | 44 ++++++++++++++++++++++++++++++++ + src/libvirt_public.syms | 1 + + src/remote/remote_driver.c | 1 + + src/remote/remote_protocol.x | 12 +++++++++ + src/remote_protocol-structs | 6 +++++ + 7 files changed, 74 insertions(+) + +diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h +index 4ab0c9c0b2..24df273045 100644 +--- a/include/libvirt/libvirt-domain.h ++++ b/include/libvirt/libvirt-domain.h +@@ -5011,4 +5011,8 @@ virDomainHotpatchManage(virDomainPtr domain, + const char *id, + unsigned int flags); + ++int virDomainStartDirtyRateCalc(virDomainPtr domain, ++ int seconds, ++ unsigned int flags); ++ + #endif /* LIBVIRT_DOMAIN_H */ +diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h +index afc21a0b3f..82f808905d 100644 +--- a/src/driver-hypervisor.h ++++ b/src/driver-hypervisor.h +@@ -1394,6 +1394,11 @@ typedef char * + const char *id, + unsigned int flags); + ++typedef int ++(*virDrvDomainStartDirtyRateCalc)(virDomainPtr domain, ++ int seconds, ++ unsigned int flags); ++ + typedef struct _virHypervisorDriver virHypervisorDriver; + typedef virHypervisorDriver *virHypervisorDriverPtr; + +@@ -1658,4 +1663,5 @@ struct _virHypervisorDriver { + virDrvDomainBackupBegin domainBackupBegin; + virDrvDomainBackupGetXMLDesc domainBackupGetXMLDesc; + virDrvDomainHotpatchManage domainHotpatchManage; ++ virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc; + }; +diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c +index 3cf6bcb3b4..974a5a5f36 100644 +--- a/src/libvirt-domain.c ++++ b/src/libvirt-domain.c +@@ -12800,3 +12800,47 @@ virDomainHotpatchManage(virDomainPtr domain, + virDispatchError(conn); + return NULL; + } ++ ++ ++/** ++ * virDomainStartDirtyRateCalc: ++ * @domain: a domain object ++ * @seconds: specified calculating time in seconds ++ * @flags: extra flags; not used yet, so callers should always pass 0 ++ * ++ * Calculate the current domain's memory dirty rate in next @seconds. ++ * The calculated dirty rate information is available by calling ++ * virConnectGetAllDomainStats. ++ * ++ * Returns 0 in case of success, -1 otherwise. ++ */ ++int ++virDomainStartDirtyRateCalc(virDomainPtr domain, ++ int seconds, ++ unsigned int flags) ++{ ++ virConnectPtr conn; ++ ++ VIR_DOMAIN_DEBUG(domain, "seconds=%d, flags=0x%x", seconds, flags); ++ ++ virResetLastError(); ++ ++ virCheckDomainReturn(domain, -1); ++ conn = domain->conn; ++ ++ virCheckReadOnlyGoto(conn->flags, error); ++ ++ if (conn->driver->domainStartDirtyRateCalc) { ++ int ret; ++ ret = conn->driver->domainStartDirtyRateCalc(domain, seconds, flags); ++ if (ret < 0) ++ goto error; ++ return ret; ++ } ++ ++ virReportUnsupportedError(); ++ ++ error: ++ virDispatchError(conn); ++ return -1; ++} +diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms +index 0ad0b9e489..f006516208 100644 +--- a/src/libvirt_public.syms ++++ b/src/libvirt_public.syms +@@ -876,5 +876,6 @@ LIBVIRT_6.0.0 { + LIBVIRT_6.2.0 { + global: + virDomainHotpatchManage; ++ virDomainStartDirtyRateCalc; + } LIBVIRT_6.0.0; + # .... define new API here using predicted next version number .... +diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c +index 1202d44017..e8ccbcb4f8 100644 +--- a/src/remote/remote_driver.c ++++ b/src/remote/remote_driver.c +@@ -8685,6 +8685,7 @@ static virHypervisorDriver hypervisor_driver = { + .domainBackupBegin = remoteDomainBackupBegin, /* 6.0.0 */ + .domainBackupGetXMLDesc = remoteDomainBackupGetXMLDesc, /* 6.0.0 */ + .domainHotpatchManage = remoteDomainHotpatchManage, /* 6.2.0 */ ++ .domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 6.2.0 */ + }; + + static virNetworkDriver network_driver = { +diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x +index ee13075ce1..d89cc1a087 100644 +--- a/src/remote/remote_protocol.x ++++ b/src/remote/remote_protocol.x +@@ -3783,6 +3783,12 @@ struct remote_domain_hotpatch_manage_ret { + remote_string info; + }; + ++struct remote_domain_start_dirty_rate_calc_args { ++ remote_nonnull_domain dom; ++ int seconds; ++ unsigned int flags; ++}; ++ + /*----- Protocol. -----*/ + + /* Define the program number, protocol version and procedure numbers here. */ +@@ -6682,6 +6688,12 @@ enum remote_procedure { + */ + REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC = 422, + ++ /** ++ * @generate: both ++ * @acl: domain:read ++ */ ++ REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427, ++ + /** + * @generate: both + * @acl: domain:read +diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs +index bae0f0b545..1e81814690 100644 +--- a/src/remote_protocol-structs ++++ b/src/remote_protocol-structs +@@ -3135,6 +3135,11 @@ struct remote_domain_backup_get_xml_desc_args { + struct remote_domain_backup_get_xml_desc_ret { + remote_nonnull_string xml; + }; ++struct remote_domain_start_dirty_rate_calc_args { ++ remote_nonnull_domain dom; ++ int seconds; ++ u_int flags; ++}; + enum remote_procedure { + REMOTE_PROC_CONNECT_OPEN = 1, + REMOTE_PROC_CONNECT_CLOSE = 2, +@@ -3558,4 +3563,5 @@ enum remote_procedure { + REMOTE_PROC_DOMAIN_AGENT_SET_RESPONSE_TIMEOUT = 420, + REMOTE_PROC_DOMAIN_BACKUP_BEGIN = 421, + REMOTE_PROC_DOMAIN_BACKUP_GET_XML_DESC = 422, ++ REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427, + }; +-- +2.27.0 + -- Gitee