From: Hyman Huang(黄勇) <yong.huang@xxxxxxxxxx> Introduce limit-dirty-page-rate virsh api to set or cancel dirty page rate upper limit for virtual CPUs. Usage is below: $ virsh limit-dirty-page-rate <domain> --rate <number> \ [--vcpu <number>] [--config] [--live] [--current] Set the dirty page rate upper limit for the given vcpu specified by the "vcpu"; set for all virtual CPUs if vcpu option is not passed in. Cancel the dirty page rate upper limit if the "rate" option is set to zero. Note that the API requires dirty-ring size configured. Signed-off-by: Hyman Huang(黄勇) <yong.huang@xxxxxxxxxx> --- docs/manpages/virsh.rst | 26 ++++++++++ tools/virsh-domain.c | 109 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 91e1d5de37..33a8f3b9fe 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -5273,6 +5273,32 @@ use to avoid keeping them open unnecessarily. Best-effort security label restore may be requested by using the *--seclabel-restore* flag. +limit-dirty-page-rate +--------------------- + +**Syntax:** + +:: + + limit-dirty-page-rate <domain> --rate <number> [--vcpu <number>] + [--config] [--live] [--current] + +Set or cancel a domain's dirty page rate upper limit for the given virtual CPU +specified by *--vcpu*; set for all virtual CPUs if *--vcpu* is not specified; +and cancel the domain's dirty page rate upper limit if *--rate* is set to zero. + +Virtual CPUs will be throttled as needed to keep their dirty page rate within +the limit if the feature enabled. This could, in some scenes, be used to provide +quality-of-service in the aspect of the memory workload for virtual CPUs. + +If *--live* is specified, affect a running domain. +If *--config* is specified, affect the next startup of a persistent domain. +If *--current* is specified, it is equivalent to either *--live* or +*--config*, depending on the current state of the domain. +Both *--live* and *--config* flags may be given, but *--current* is +exclusive. Not specifying any flag is the same as specifying *--current*. + + NODEDEV COMMANDS ================ diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 7abafe2ba3..ae51d9fdfb 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -13732,6 +13732,109 @@ cmdDomDirtyRateCalc(vshControl *ctl, const vshCmd *cmd) return true; } +/* + * "limit-dirty-page-rate" command + */ +static const vshCmdInfo info_limit_dirty_page_rate[] = { + {.name = "help", + .data = N_("Set or cancel dirty page rate upper limit") + }, + {.name = "desc", + .data = N_("Set or cancel dirty page rate upper limit, " + "require dirty-ring size configured") + }, + {.name = NULL} +}; + +static const vshCmdOptDef opts_limit_dirty_page_rate[] = { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name = "rate", + .type = VSH_OT_INT, + .flags = VSH_OFLAG_REQ, + .help = N_("Upper limit of dirty page rate (MB/s) for " + "virtual CPUs, use 0 to cancel") + }, + {.name = "vcpu", + .type = VSH_OT_INT, + .help = N_("Index of a virtual CPU") + }, + VIRSH_COMMON_OPT_DOMAIN_PERSISTENT, + VIRSH_COMMON_OPT_DOMAIN_CONFIG, + VIRSH_COMMON_OPT_DOMAIN_LIVE, + VIRSH_COMMON_OPT_DOMAIN_CURRENT, + {.name = NULL} +}; + +static bool +cmdLimitDirtyPageRate(vshControl *ctl, const vshCmd *cmd) +{ + g_autoptr(virshDomain) dom = NULL; + int vcpu_idx = -1; + unsigned long long rate = 0; + unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT; + bool vcpu = vshCommandOptBool(cmd, "vcpu"); + bool current = vshCommandOptBool(cmd, "current"); + bool config = vshCommandOptBool(cmd, "config"); + bool live = vshCommandOptBool(cmd, "live"); + + VSH_EXCLUSIVE_OPTIONS_VAR(current, live); + VSH_EXCLUSIVE_OPTIONS_VAR(current, config); + + if (config) + flags |= VIR_DOMAIN_AFFECT_CONFIG; + if (live) + flags |= VIR_DOMAIN_AFFECT_LIVE; + + if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) + return false; + + if (vshCommandOptULongLong(ctl, cmd, "rate", &rate) < 0) + return false; + + if (vcpu) { + if (vshCommandOptInt(ctl, cmd, "vcpu", &vcpu_idx) < 0) + return false; + + if (vcpu_idx < 0) { + vshError(ctl, "%s", + _("Invalid vcpu index, using --vcpu to specify cpu index")); + return false; + } + } + + if (vcpu) { + /* Set the dirty page rate upper limit for the specified + * virtual CPU in the given VM; cancel it if rate is set + * to zero. + */ + if (virDomainSetVcpuDirtyLimit(dom, vcpu_idx, + rate, flags) < 0) + return false; + if (rate == 0) + vshPrintExtra(ctl, + _("Cancel vcpu[%1$d] dirty page rate upper limit successfully\n"), + vcpu_idx); + else + vshPrintExtra(ctl, + _("Set vcpu[%1$d] dirty page rate upper limit %2$lld(MB/s) successfully\n"), + vcpu_idx, rate); + } else { + /* Set all dirty page rate upper limits for virtual CPUs in + * the given VM; cancel it if the rate is set to zero. + */ + if (virDomainSetVcpuDirtyLimit(dom, -1, rate, flags) < 0) + return false; + if (rate == 0) + vshPrintExtra(ctl, "%s", + _("Cancel dirty page rate limit for all virtual CPUs successfully\n")); + else + vshPrintExtra(ctl, + _("Set dirty page rate limit %1$lld(MB/s) for all virtual CPUs successfully\n"), + rate); + } + + return true; +} const vshCmdDef domManagementCmds[] = { {.name = "attach-device", @@ -14396,5 +14499,11 @@ const vshCmdDef domManagementCmds[] = { .info = info_dom_fd_associate, .flags = 0 }, + {.name = "limit-dirty-page-rate", + .handler = cmdLimitDirtyPageRate, + .opts = opts_limit_dirty_page_rate, + .info = info_limit_dirty_page_rate, + .flags = 0 + }, {.name = NULL} }; -- 2.38.5