[PATCH v6 0/5] migration/dirtyrate: Introduce APIs for getting domain memory dirty rate

V5 -> V6: split DomainGetDirtyRateInfo(domdirtyrate) API into two parts: 1. DomainStartDirtyRateCalc(domdirtyrate-calc) for starting dirty rate calculation; 2. qemuDomainGetStatsDirtyRate(domstats --dirtyrate) for querying dirty rate infomation. V4 -> V5: squash 1/7 and bits of 5/7 and 6/7 into 2/7 in v4 (to be 1/5 in v5) squash left of 5/7 into 4/7 in v4 (to be 3/5 in v5) add VIR_DOMAIN_DIRTYRATE_DEFAULT flag remove redundant error report rename virsh api to "domdirtyrate" use vshTablePtr for virsh api output add description in docs/manpages/virsh.rst other format optimize V3 -> V4: define flags to unsigned int fix some compile warnings V2 -> V3: reorganize patchset to fix compile warning V1 -> V2: replace QEMU_JOB_ASYNC with QEMU_JOB_QUERY Sometimes domain's memory dirty rate is expected by user in order to decide whether it's proper to be migrated out or not. We have already completed the QEMU part of the capability: https://patchew.org/QEMU/1600237327-33618-1-git-send-email-zhengchuan@huawei... And this serial of patches introduce the corresponding LIBVIRT part: 1. Calculating Introduce a new API DomainStartDirtyRateCalc and corresponding virsh api (domdirtyrate-calc) for starting dirty rate calculation by calling qmp 'calc-dirty-rate'. # virsh domdirtyrate-calc <domain> [--seconds <sec>] 2. Querying Introduce command 'virsh domstats --dirtyrate' for reporting memory dirty rate infomation by calling qmp 'query-dirty-rate'. The info is listed as: Domain: 'vm0' dirtyrate.calc_status=measured dirtyrate.calc_start_time=502814 dirtyrate.calc_period=1 dirtyrate.megabytes_per_second=2 Hao Wang (5): migration/dirtyrate: Introduce virDomainStartDirtyRateCalc API migration/dirtyrate: Implement qemuDomainStartDirtyRateCalc migration/dirtyrate: Introduce domdirtyrate-calc virsh api migration/dirtyrate: Implement qemuMonitorQueryDirtyRate migration/dirtyrate: Introduce command 'virsh domstats --dirtyrate' docs/manpages/virsh.rst | 33 ++++++++- include/libvirt/libvirt-domain.h | 5 ++ src/driver-hypervisor.h | 6 ++ src/libvirt-domain.c | 57 +++++++++++++++ src/libvirt_public.syms | 5 ++ src/qemu/qemu_driver.c | 115 +++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 24 +++++++ src/qemu/qemu_monitor.h | 18 +++++ src/qemu/qemu_monitor_json.c | 88 +++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 8 +++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 14 +++- src/remote_protocol-structs | 6 ++ tools/virsh-domain-monitor.c | 7 ++ tools/virsh-domain.c | 63 +++++++++++++++++ 15 files changed, 447 insertions(+), 3 deletions(-) -- 2.23.0

Introduce virDomainStartDirtyRateCalc API for start calculation of a domain's memory dirty rate with a specified time. Signed-off-by: Hao Wang <wanghao232@huawei.com> --- include/libvirt/libvirt-domain.h | 4 +++ src/driver-hypervisor.h | 6 +++++ src/libvirt-domain.c | 44 ++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 ++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 14 +++++++++- src/remote_protocol-structs | 6 +++++ 7 files changed, 79 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 8011cf9fe1..7aa5ef4543 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5128,4 +5128,8 @@ int virDomainGetMessages(virDomainPtr domain, char ***msgs, 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 05d7dfb5c7..2ec7b8b24a 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1405,6 +1405,11 @@ typedef int char ***msgs, unsigned int flags); +typedef int +(*virDrvDomainStartDirtyRateCalc)(virDomainPtr domain, + int seconds, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1671,4 +1676,5 @@ struct _virHypervisorDriver { virDrvDomainAuthorizedSSHKeysGet domainAuthorizedSSHKeysGet; virDrvDomainAuthorizedSSHKeysSet domainAuthorizedSSHKeysSet; virDrvDomainGetMessages domainGetMessages; + virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 4af0166872..b1cc2ebbf3 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -13154,3 +13154,47 @@ virDomainGetMessages(virDomainPtr domain, virDispatchError(conn); return -1; } + + +/** + * 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 infomation 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 d851333eb0..51a3d7265a 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -884,4 +884,9 @@ LIBVIRT_7.1.0 { virDomainGetMessages; } LIBVIRT_6.10.0; +LIBVIRT_7.2.0 { + global: + virDomainStartDirtyRateCalc; +} LIBVIRT_7.1.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 a83cd866e7..3968472931 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8575,6 +8575,7 @@ static virHypervisorDriver hypervisor_driver = { .domainAuthorizedSSHKeysGet = remoteDomainAuthorizedSSHKeysGet, /* 6.10.0 */ .domainAuthorizedSSHKeysSet = remoteDomainAuthorizedSSHKeysSet, /* 6.10.0 */ .domainGetMessages = remoteDomainGetMessages, /* 7.1.0 */ + .domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index d3724bc305..7fdc65f029 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -3811,6 +3811,12 @@ struct remote_domain_get_messages_ret { remote_nonnull_string msgs<REMOTE_DOMAIN_MESSAGES_MAX>; }; +struct remote_domain_start_dirty_rate_calc_args { + remote_nonnull_domain dom; + int seconds; + unsigned int flags; +}; + /*----- Protocol. -----*/ @@ -6733,5 +6739,11 @@ enum remote_procedure { * @generate: none * @acl: domain:read */ - REMOTE_PROC_DOMAIN_GET_MESSAGES = 426 + REMOTE_PROC_DOMAIN_GET_MESSAGES = 426, + + /** + * @generate: both + * @acl: domain:read + */ + REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index c0c034ac6a..d13dc81a82 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -3172,6 +3172,11 @@ struct remote_domain_get_messages_ret { remote_nonnull_string * msgs_val; } msgs; }; +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, @@ -3599,4 +3604,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_GET = 424, REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_SET = 425, REMOTE_PROC_DOMAIN_GET_MESSAGES = 426, + REMOTE_PROC_DOMAIN_START_DIRTY_RATE_CALC = 427, }; -- 2.23.0

On 2/26/21 9:35 AM, Hao Wang wrote:
Introduce virDomainStartDirtyRateCalc API for start calculation of a domain's memory dirty rate with a specified time.
Signed-off-by: Hao Wang <wanghao232@huawei.com> --- include/libvirt/libvirt-domain.h | 4 +++ src/driver-hypervisor.h | 6 +++++ src/libvirt-domain.c | 44 ++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 ++++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 14 +++++++++- src/remote_protocol-structs | 6 +++++ 7 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 4af0166872..b1cc2ebbf3 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -13154,3 +13154,47 @@ virDomainGetMessages(virDomainPtr domain, virDispatchError(conn); return -1; } + + +/** + * 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 infomation is available by calling
information
+ * 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; +}
Michal

Implement qemuDomainStartDirtyRateCalc which calculates domain's memory dirty rate calling qmp "calc-dirty-rate". Signed-off-by: Hao Wang <wanghao232@huawei.com> --- src/qemu/qemu_driver.c | 59 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 12 ++++++++ src/qemu/qemu_monitor.h | 4 +++ src/qemu/qemu_monitor_json.c | 22 ++++++++++++++ src/qemu/qemu_monitor_json.h | 4 +++ 5 files changed, 101 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b9bbdf8d48..7420937cf7 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20302,6 +20302,64 @@ qemuDomainGetMessages(virDomainPtr dom, } +#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, @@ -20544,6 +20602,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainAuthorizedSSHKeysGet = qemuDomainAuthorizedSSHKeysGet, /* 6.10.0 */ .domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */ .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */ + .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 73f337a6be..05c57f5f1d 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4742,3 +4742,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 d25c26343a..94813906b4 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1526,3 +1526,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 b2034b3a40..e6c127ab61 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -9483,3 +9483,25 @@ qemuMonitorJSONGetCPUMigratable(qemuMonitorPtr mon, return virJSONValueGetBoolean(virJSONValueObjectGet(reply, "return"), migratable); } + + +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 3dd1eb24c7..32782cf681 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -711,3 +711,7 @@ int qemuMonitorJSONSetDBusVMStateIdList(qemuMonitorPtr mon, int qemuMonitorJSONGetCPUMigratable(qemuMonitorPtr mon, bool *migratable); + +int +qemuMonitorJSONStartDirtyRateCalc(qemuMonitorPtr mon, + int seconds); -- 2.23.0

Introduce domdirtyrate-calc virsh api to start calculating domain's memory dirty rate: # virsh domdirtyrate-calc <domain> [--seconds <sec>] Signed-off-by: Hao Wang <wanghao232@huawei.com> --- docs/manpages/virsh.rst | 17 +++++++++++ tools/virsh-domain.c | 63 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 8a4328faa0..417ea444f4 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1704,6 +1704,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 <domain> [--seconds <sec>] + +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 infomation is available by calling +'domstats --dirtyrate'. + + domdisplay ---------- diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index df33467646..ccb5d61a25 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -14412,6 +14412,63 @@ cmdSetUserSSHKeys(vshControl *ctl, const vshCmd *cmd) } +/* + * "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 infomation 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; + int rc; + bool ret = false; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + rc = vshCommandOptInt(ctl, cmd, "seconds", &seconds); + if (rc < 0) + goto cleanup; + + /* if no inputted seconds, default to 1s */ + if (!rc) + seconds = 1; + + if (virDomainStartDirtyRateCalc(dom, seconds, 0) < 0) + goto cleanup; + + vshPrint(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, @@ -15051,5 +15108,11 @@ const vshCmdDef domManagementCmds[] = { .info = info_guestinfo, .flags = 0 }, + {.name = "domdirtyrate-calc", + .handler = cmdDomDirtyRateCalc, + .opts = opts_domdirtyrate_calc, + .info = info_domdirtyrate_calc, + .flags = 0 + }, {.name = NULL} }; -- 2.23.0

On 2/26/21 9:35 AM, Hao Wang wrote:
Introduce domdirtyrate-calc virsh api to start calculating domain's memory dirty rate: # virsh domdirtyrate-calc <domain> [--seconds <sec>]
Signed-off-by: Hao Wang <wanghao232@huawei.com> --- docs/manpages/virsh.rst | 17 +++++++++++ tools/virsh-domain.c | 63 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 8a4328faa0..417ea444f4 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -1704,6 +1704,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 <domain> [--seconds <sec>] + +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 infomation is available by calling +'domstats --dirtyrate'. + + domdisplay ----------
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index df33467646..ccb5d61a25 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -14412,6 +14412,63 @@ cmdSetUserSSHKeys(vshControl *ctl, const vshCmd *cmd) }
+/* + * "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 infomation 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; + int rc; + bool ret = false; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + rc = vshCommandOptInt(ctl, cmd, "seconds", &seconds); + if (rc < 0) + goto cleanup; + + /* if no inputted seconds, default to 1s */ + if (!rc) + seconds = 1;
The vshCommandOptInt() (and others too for that matter) are designed so that if --argument is not present, then the destination variable is not touched. So this can be rewritten as: int seconds = 1; /* the default value is 1 */ rc = vshCommandOptInt(ctl, cmd, "seconds", &seconds); if (rc < 0) goto cleanup; and since @rc is not used anywhere else it's not needed and thus can be dropped.
+ + if (virDomainStartDirtyRateCalc(dom, seconds, 0) < 0) + goto cleanup; + + vshPrint(ctl, _("Start to calculate domain's memory dirty rate successfully.\n"));
This could be vshPrintExtra(). That's what we tend to use for this affirmation prints. 'virsh -q' is quiet and can be used from a script, 'virsh' run by users gives them good feeling of something happening. Michal

Implement qemuMonitorQueryDirtyRate which query domain's memory dirty rate calling qmp "query-dirty-rate". Signed-off-by: Hao Wang <wanghao232@huawei.com> --- src/qemu/qemu_monitor.c | 12 +++++++ src/qemu/qemu_monitor.h | 14 ++++++++ src/qemu/qemu_monitor_json.c | 66 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 4 +++ 4 files changed, 96 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 05c57f5f1d..dcc529b405 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4754,3 +4754,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 94813906b4..9958657c2c 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1530,3 +1530,17 @@ qemuMonitorTransactionBackup(virJSONValuePtr actions, int qemuMonitorStartDirtyRateCalc(qemuMonitorPtr mon, int seconds); + +typedef struct _qemuMonitorDirtyRateInfo qemuMonitorDirtyRateInfo; +typedef qemuMonitorDirtyRateInfo *qemuMonitorDirtyRateInfoPtr; + +struct _qemuMonitorDirtyRateInfo { + char *status; /* the status of last dirtyrate calculation */ + long long dirtyRate; /* the dirtyrate in MiB/s */ + long long startTime; /* the start time of dirtyrate calculation */ + int calcTime; /* the period of dirtyrate calculation */ +}; + +int +qemuMonitorQueryDirtyRate(qemuMonitorPtr mon, + qemuMonitorDirtyRateInfoPtr info); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index e6c127ab61..409fb817bf 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -9505,3 +9505,69 @@ qemuMonitorJSONStartDirtyRateCalc(qemuMonitorPtr mon, return 0; } + + +static int +qemuMonitorJSONExtractDirtyRateInfo(virJSONValuePtr data, + qemuMonitorDirtyRateInfoPtr info) +{ + const char *status; + + if (!(status = virJSONValueObjectGetString(data, "status"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-dirty-rate reply was missing 'status' data")); + return -1; + } + info->status = g_strdup(status); + + /* `query-dirty-rate` replies `dirty-rate` data only if the status of the latest + * calculation is `measured`. + */ + if (STREQ(info->status, "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 32782cf681..8d4232f67b 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -715,3 +715,7 @@ qemuMonitorJSONGetCPUMigratable(qemuMonitorPtr mon, int qemuMonitorJSONStartDirtyRateCalc(qemuMonitorPtr mon, int seconds); + +int +qemuMonitorJSONQueryDirtyRate(qemuMonitorPtr mon, + qemuMonitorDirtyRateInfoPtr info); -- 2.23.0

Introduce command 'virsh domstats --dirtyrate' for reporting memory dirty rate infomation. The info is listed as: Domain: 'vm0' dirtyrate.calc_status=measured dirtyrate.calc_start_time=502814 dirtyrate.calc_period=1 dirtyrate.megabytes_per_second=2 Signed-off-by: Hao Wang <wanghao232@huawei.com> --- docs/manpages/virsh.rst | 16 +++++++-- include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 13 ++++++++ src/qemu/qemu_driver.c | 56 ++++++++++++++++++++++++++++++++ tools/virsh-domain-monitor.c | 7 ++++ 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 417ea444f4..b0fab3e781 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2219,7 +2219,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 ...] @@ -2238,7 +2238,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. @@ -2431,6 +2432,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 +* ``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/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 7aa5ef4543..81371f54b7 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -2185,6 +2185,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 b1cc2ebbf3..0a03b2ca90 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11883,6 +11883,19 @@ 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 + * "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 + * * 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 7420937cf7..f847650e22 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18535,6 +18535,61 @@ 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; + int ret = -1; + + if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom)) + return 0; + + if (qemuDomainGetStatsDirtyRateMon(driver, dom, &info) < 0) + goto cleanup; + + if (virTypedParamListAddString(params, info.status, + "dirtyrate.calc_status") < 0) + goto cleanup; + + if (virTypedParamListAddLLong(params, info.startTime, + "dirtyrate.calc_start_time") < 0) + goto cleanup; + + if (virTypedParamListAddInt(params, info.calcTime, + "dirtyrate.calc_period") < 0) + goto cleanup; + + if (STREQ(info.status, "measured") && + virTypedParamListAddLLong(params, info.dirtyRate, + "dirtyrate.megabytes_per_second") < 0) + goto cleanup; + + ret = 0; + + cleanup: + VIR_FREE(info.status); + return ret; +} + typedef int (*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver, virDomainObjPtr dom, @@ -18557,6 +18612,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 } }; diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index 897339b6f9..c4d7464695 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -2148,6 +2148,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"), @@ -2267,6 +2271,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.23.0

On 2/26/21 9:35 AM, Hao Wang wrote:
Introduce command 'virsh domstats --dirtyrate' for reporting memory dirty rate infomation. The info is listed as:
Domain: 'vm0' dirtyrate.calc_status=measured dirtyrate.calc_start_time=502814 dirtyrate.calc_period=1 dirtyrate.megabytes_per_second=2
Signed-off-by: Hao Wang <wanghao232@huawei.com> --- docs/manpages/virsh.rst | 16 +++++++-- include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 13 ++++++++ src/qemu/qemu_driver.c | 56 ++++++++++++++++++++++++++++++++ tools/virsh-domain-monitor.c | 7 ++++ 5 files changed, 91 insertions(+), 2 deletions(-)
There are two things happening in this patch. You're extending virsh and at the same time introducing new domain statistics. I think they should go separate (it'd be easier to backport for instance).
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 417ea444f4..b0fab3e781 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2219,7 +2219,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 ...] @@ -2238,7 +2238,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. @@ -2431,6 +2432,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 +* ``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/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 7aa5ef4543..81371f54b7 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -2185,6 +2185,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;
I think this hunk doesn't belong here.
typedef enum { diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index b1cc2ebbf3..0a03b2ca90 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11883,6 +11883,19 @@ 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
I'm not sure we want to expose this as string. At the same time, we don't have any enum defined, yet. What do others think?
+ * "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
Notice how the other descriptions have "as unsigned int" or "as long long"? That is so that a developer reading this description knows which one of virTypedParamsGet*() family to call. For instance, if I'd be interested in calc_start_time, then I can do: long long dirtyrate; virDomainListGetStats(domlist, VIR_DOMAIN_STATS_DIRTYRATE, &records, 0); virTypedParamsGetLLong(records->params, records->nparams, "dirtyrate.megabytes_per_second", &dirtyrate);
+ * * 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
I think this should be in the other patch too.
index 7420937cf7..f847650e22 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18535,6 +18535,61 @@ 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; + int ret = -1; + + if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom)) + return 0; + + if (qemuDomainGetStatsDirtyRateMon(driver, dom, &info) < 0) + goto cleanup; + + if (virTypedParamListAddString(params, info.status, + "dirtyrate.calc_status") < 0) + goto cleanup; + + if (virTypedParamListAddLLong(params, info.startTime, + "dirtyrate.calc_start_time") < 0) + goto cleanup; + + if (virTypedParamListAddInt(params, info.calcTime, + "dirtyrate.calc_period") < 0) + goto cleanup; + + if (STREQ(info.status, "measured") && + virTypedParamListAddLLong(params, info.dirtyRate, + "dirtyrate.megabytes_per_second") < 0) + goto cleanup; + + ret = 0; + + cleanup: + VIR_FREE(info.status); + return ret; +} + typedef int (*qemuDomainGetStatsFunc)(virQEMUDriverPtr driver, virDomainObjPtr dom, @@ -18557,6 +18612,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 } };
Theset two hunks should be in the other patch.
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index 897339b6f9..c4d7464695 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -2148,6 +2148,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"), @@ -2267,6 +2271,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;
Michal

On 2/26/21 9:35 AM, Hao Wang wrote:
V5 -> V6: split DomainGetDirtyRateInfo(domdirtyrate) API into two parts: 1. DomainStartDirtyRateCalc(domdirtyrate-calc) for starting dirty rate calculation; 2. qemuDomainGetStatsDirtyRate(domstats --dirtyrate) for querying dirty rate infomation.
V4 -> V5: squash 1/7 and bits of 5/7 and 6/7 into 2/7 in v4 (to be 1/5 in v5) squash left of 5/7 into 4/7 in v4 (to be 3/5 in v5) add VIR_DOMAIN_DIRTYRATE_DEFAULT flag remove redundant error report rename virsh api to "domdirtyrate" use vshTablePtr for virsh api output add description in docs/manpages/virsh.rst other format optimize
V3 -> V4: define flags to unsigned int fix some compile warnings
V2 -> V3: reorganize patchset to fix compile warning
V1 -> V2: replace QEMU_JOB_ASYNC with QEMU_JOB_QUERY
Sometimes domain's memory dirty rate is expected by user in order to decide whether it's proper to be migrated out or not.
We have already completed the QEMU part of the capability: https://patchew.org/QEMU/1600237327-33618-1-git-send-email-zhengchuan@huawei... And this serial of patches introduce the corresponding LIBVIRT part:
1. Calculating Introduce a new API DomainStartDirtyRateCalc and corresponding virsh api (domdirtyrate-calc) for starting dirty rate calculation by calling qmp 'calc-dirty-rate'.
# virsh domdirtyrate-calc <domain> [--seconds <sec>]
2. Querying Introduce command 'virsh domstats --dirtyrate' for reporting memory dirty rate infomation by calling qmp 'query-dirty-rate'.
The info is listed as: Domain: 'vm0' dirtyrate.calc_status=measured dirtyrate.calc_start_time=502814 dirtyrate.calc_period=1 dirtyrate.megabytes_per_second=2
Hao Wang (5): migration/dirtyrate: Introduce virDomainStartDirtyRateCalc API migration/dirtyrate: Implement qemuDomainStartDirtyRateCalc migration/dirtyrate: Introduce domdirtyrate-calc virsh api migration/dirtyrate: Implement qemuMonitorQueryDirtyRate migration/dirtyrate: Introduce command 'virsh domstats --dirtyrate'
docs/manpages/virsh.rst | 33 ++++++++- include/libvirt/libvirt-domain.h | 5 ++ src/driver-hypervisor.h | 6 ++ src/libvirt-domain.c | 57 +++++++++++++++ src/libvirt_public.syms | 5 ++ src/qemu/qemu_driver.c | 115 +++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 24 +++++++ src/qemu/qemu_monitor.h | 18 +++++ src/qemu/qemu_monitor_json.c | 88 +++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 8 +++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 14 +++- src/remote_protocol-structs | 6 ++ tools/virsh-domain-monitor.c | 7 ++ tools/virsh-domain.c | 63 +++++++++++++++++ 15 files changed, 447 insertions(+), 3 deletions(-)
To patches 1-4: Reviewed-by: Michal Privoznik <mprivozn@redhat.com> The last one 5/5 should be split. And I'd wait for others to give opinion on the enum vs string representation of calc_status. If we go with enum, then I think _qemuMonitorDirtyRateInfo struct in 4/5 should be updated to reflect this change. We are almost there! Michal

Great thanks for your reviewing! I will update 5/5 and possibly 4/5 according to expected more suggestion in the next version. BR, Hao On 2021/3/3 19:31, Michal Privoznik wrote:
On 2/26/21 9:35 AM, Hao Wang wrote:
Hao Wang (5): migration/dirtyrate: Introduce virDomainStartDirtyRateCalc API migration/dirtyrate: Implement qemuDomainStartDirtyRateCalc migration/dirtyrate: Introduce domdirtyrate-calc virsh api migration/dirtyrate: Implement qemuMonitorQueryDirtyRate migration/dirtyrate: Introduce command 'virsh domstats --dirtyrate'
docs/manpages/virsh.rst | 33 ++++++++- include/libvirt/libvirt-domain.h | 5 ++ src/driver-hypervisor.h | 6 ++ src/libvirt-domain.c | 57 +++++++++++++++ src/libvirt_public.syms | 5 ++ src/qemu/qemu_driver.c | 115 +++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 24 +++++++ src/qemu/qemu_monitor.h | 18 +++++ src/qemu/qemu_monitor_json.c | 88 +++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 8 +++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 14 +++- src/remote_protocol-structs | 6 ++ tools/virsh-domain-monitor.c | 7 ++ tools/virsh-domain.c | 63 +++++++++++++++++ 15 files changed, 447 insertions(+), 3 deletions(-)
To patches 1-4:
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
The last one 5/5 should be split. And I'd wait for others to give opinion on the enum vs string representation of calc_status. If we go with enum, then I think _qemuMonitorDirtyRateInfo struct in 4/5 should be updated to reflect this change.
We are almost there!
Michal
.
participants (2)
-
Hao Wang
-
Michal Privoznik