On Wed, Feb 19, 2025 at 22:27:11 +0530, Harikumar Rajkumar wrote: > From: Chun Feng Wu <danielw...@163.com> > > Defined new public APIs: > * virDomainSetThrottleGroup to add or update throttlegroup within specific > domain, > it will be referenced by throttlefilter later in disk to do limits > * virDomainGetThrottleGroup to get throttlegroup info, old-style is discarded > (APIs to query first for the number of parameters and then give it a > reasonably-sized pointer), instead, the new approach is adopted that > API returns allocated array of fields and number of fileds that are in it. > * virDomainDelThrottleGroup to delete throttlegroup, it fails if this > throttlegroup > is still referenced by some throttlefilter > > Signed-off-by: Chun Feng Wu <danielw...@163.com> > > * Reimplement getter API to fetch data from XML. > * Apply suggested coding style changes. > * Update of code documentation comments. > * Update the version to 11.1.0.
I'll update all including this to 11.2.0 > > Signed-off-by: Harikumar Rajkumar <harirajkumar...@gmail.com> > --- > include/libvirt/libvirt-domain.h | 14 ++++ > src/driver-hypervisor.h | 14 ++++ > src/libvirt-domain.c | 122 ++++++++++++++++++++++++++++ > src/libvirt_private.syms | 8 ++ > src/libvirt_public.syms | 6 ++ > src/qemu/qemu_monitor.c | 13 --- > src/qemu/qemu_monitor.h | 5 -- > src/remote/remote_daemon_dispatch.c | 105 ++++++++++++++++++++++++ > src/remote/remote_driver.c | 3 + > src/remote/remote_protocol.x | 50 +++++++++++- > src/remote_protocol-structs | 28 +++++++ > 11 files changed, 349 insertions(+), 19 deletions(-) [...] > diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c > index 072cc32255..326bbd9abb 100644 > --- a/src/libvirt-domain.c > +++ b/src/libvirt-domain.c > @@ -14162,3 +14162,125 @@ virDomainGraphicsReload(virDomainPtr domain, > virDispatchError(domain->conn); > return -1; > } > + > + > +/** > + * virDomainSetThrottleGroup: > + * @dom: pointer to domain object > + * @group: throttle group name > + * @params: Pointer to blkio parameter objects > + * @nparams: Number of blkio parameters (this value can be the same or > + * less than the number of parameters supported) > + * @flags: bitwise-OR of virDomainModificationImpact > + * > + * Add throttlegroup or change all of the throttlegroup options > + * within specific domain > + * > + * The @group parameter is the name for new or existing throttlegroup, > + * it cannot be NULL, detailed throttlegroup info is included in @params, > + * it either creates new throttlegroup with @params or updates existing > + * throttlegroup with @params, throttlegroup can be referenced by throttle > + * filter in attached disk to do limits, the difference from iotune is that > + * multiple throttlegroups can be referenced within attached disk > + * > + * Returns -1 in case of error, 0 in case of success. > + * > + * Since: 11.1.0 ^^^ > + */ > +int > +virDomainSetThrottleGroup(virDomainPtr dom, > + const char *group, > + virTypedParameterPtr params, > + int nparams, > + unsigned int flags) > +{ > + virConnectPtr conn; > + > + VIR_DOMAIN_DEBUG(dom, "params=%p, group='%s', nparams=%d, flags=0x%x", > + params, group, nparams, flags); > + VIR_TYPED_PARAMS_DEBUG(params, nparams); > + > + virResetLastError(); > + > + virCheckDomainReturn(dom, -1); > + conn = dom->conn; > + > + virCheckReadOnlyGoto(conn->flags, error); > + virCheckNonNullArgGoto(group, error); > + virCheckPositiveArgGoto(nparams, error); > + virCheckNonNullArgGoto(params, error); > + > + if (virTypedParameterValidateSet(dom->conn, params, nparams) < 0) > + goto error; > + > + if (conn->driver->domainSetThrottleGroup) { > + int ret; > + ret = conn->driver->domainSetThrottleGroup(dom, group, params, > nparams, flags); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virReportUnsupportedError(); > + > + error: > + virDispatchError(dom->conn); > + return -1; > +} > + > + > +/** > + * virDomainDelThrottleGroup: > + * @dom: pointer to domain object > + * @group: throttle group name > + * @flags: bitwise-OR of virDomainModificationImpact > + * > + * Delete an throttlegroup from the domain. @group cannot be NULL, > + * and the @group to be deleted must not have a throttlefilter associated > with > + * it and can be any of the current valid group. > + * > + * @flags may include VIR_DOMAIN_AFFECT_LIVE or VIR_DOMAIN_AFFECT_CONFIG. > + * Both flags may be set. > + * If VIR_DOMAIN_AFFECT_LIVE is set, the change affects a running domain > + * and may fail if domain is not alive. > + * If VIR_DOMAIN_AFFECT_CONFIG is set, the change affects persistent state, > + * and will fail for transient domains. If neither flag is specified (that > is, > + * @flags is VIR_DOMAIN_AFFECT_CURRENT), then an inactive domain modifies > + * persistent setup, while an active domain is hypervisor-dependent on > whether > + * just live or both live and persistent state is changed. > + * > + * Returns -1 in case of error, 0 in case of success. > + * > + * Since: 11.1.0 ^^^ > + */ > +int > +virDomainDelThrottleGroup(virDomainPtr dom, > + const char *group, > + unsigned int flags) > +{ [...] > diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms > index 7a3492d9d7..7448bcb1f0 100644 > --- a/src/libvirt_public.syms > +++ b/src/libvirt_public.syms > @@ -948,4 +948,10 @@ LIBVIRT_10.2.0 { > virDomainGraphicsReload; > } LIBVIRT_10.1.0; > > +LIBVIRT_11.1.0 { ^^^ > + global: > + virDomainSetThrottleGroup; > + virDomainDelThrottleGroup; > +} LIBVIRT_10.2.0; > + > # .... define new API here using predicted next version number .... > diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c > index 015f8f11cc..89669ccb15 100644 > --- a/src/qemu/qemu_monitor.c > +++ b/src/qemu/qemu_monitor.c > @@ -3058,19 +3058,6 @@ qemuMonitorUpdateThrottleGroup(qemuMonitor *mon, > } > > > -int > -qemuMonitorGetThrottleGroup(qemuMonitor *mon, > - const char *groupname, > - virDomainBlockIoTuneInfo *reply) > -{ > - VIR_DEBUG("throttle-group=%s, reply=%p", groupname, reply); > - > - QEMU_CHECK_MONITOR(mon); > - > - return qemuMonitorJSONGetThrottleGroup(mon, groupname, reply); > -} > - > - > int > qemuMonitorVMStatusToPausedReason(const char *status) > { This definitely doesn't belong to this patch. > diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h > index 7b58d988d8..c6332630bd 100644 > --- a/src/qemu/qemu_monitor.h > +++ b/src/qemu/qemu_monitor.h > @@ -1083,11 +1083,6 @@ qemuMonitorUpdateThrottleGroup(qemuMonitor *mon, > const char *qomid, > virDomainBlockIoTuneInfo *info); > > -int > -qemuMonitorGetThrottleGroup(qemuMonitor *mon, > - const char *groupname, > - virDomainBlockIoTuneInfo *reply); > - > int qemuMonitorSystemWakeup(qemuMonitor *mon); Same here. > > int qemuMonitorGetVersion(qemuMonitor *mon, > diff --git a/src/remote/remote_daemon_dispatch.c > b/src/remote/remote_daemon_dispatch.c > index e812f5c3e9..2781e70396 100644 > --- a/src/remote/remote_daemon_dispatch.c > +++ b/src/remote/remote_daemon_dispatch.c > @@ -3618,6 +3618,111 @@ remoteDispatchDomainGetBlockIoTune(virNetServer > *server G_GNUC_UNUSED, > return rv; > } > > +#define PARSE_THROTTLER_GROUP(val) \ > + if (virXPathULongLong("string(./" #val ")", \ > + ctxt, &throttleGroup->val) == -2) { \ > + goto cleanup; \ > + } \ > + if ((virTypedParamsAddULLong(¶ms, &nparams, &maxparams, \ > + #val, throttleGroup->val) < 0)) { \ > + goto cleanup; \ > + } > + > +static int > +remoteDispatchDomainGetThrottleGroup(virNetServer *server G_GNUC_UNUSED, > + virNetServerClient *client, > + virNetMessage *hdr G_GNUC_UNUSED, > + struct virNetMessageError *rerr, > + remote_domain_get_throttle_group_args > *args, > + remote_domain_get_throttle_group_ret > *ret) The getter doesn't exist so this doesn't make sense either. > +{ > + virDomainPtr dom = NULL; > + int rv = -1; > + g_autofree char *doc = NULL; > + g_autoptr(xmlDoc) xml = NULL; > + g_autoptr(xmlXPathContext) ctxt = NULL; > + g_autofree xmlNodePtr *node = NULL; > + int n = 0; > + int maxparams = 0; > + size_t i; > + > + virTypedParameterPtr params = NULL; > + int nparams = 0; > + virConnectPtr conn = remoteGetHypervisorConn(client); > + > + if (!conn) > + goto cleanup; > + > + if (!(dom = get_nonnull_domain(conn, args->dom))) > + goto cleanup; > + virCheckNonNullArgGoto(*args->group, cleanup); > + > + doc = virDomainGetXMLDesc(dom, args->flags); > + > + if (!(xml = virXMLParseStringCtxt(doc, _("(domain_definition)"), > &ctxt))) { > + return false; > + } > + > + if ((n = virXPathNodeSet("/domain/throttlegroups/throttlegroup", ctxt, > &node)) < 0) > + goto cleanup; > + > + if (n == 0) > + return 0; > + > + for (i = 0; i < n; i++) { > + g_autoptr(virDomainThrottleGroupDef) throttleGroup = > g_new0(virDomainThrottleGroupDef, 1); > + > + VIR_XPATH_NODE_AUTORESTORE(ctxt) > + ctxt->node = node[i]; > + > + if (STREQ(*args->group, virXPathString("string(./group_name)", > ctxt)) == 0) { > + continue; > + } > + > + PARSE_THROTTLER_GROUP(total_bytes_sec); > + PARSE_THROTTLER_GROUP(read_bytes_sec); > + PARSE_THROTTLER_GROUP(write_bytes_sec); > + PARSE_THROTTLER_GROUP(total_iops_sec); > + PARSE_THROTTLER_GROUP(read_iops_sec); > + PARSE_THROTTLER_GROUP(write_iops_sec); > + > + PARSE_THROTTLER_GROUP(total_bytes_sec_max); > + PARSE_THROTTLER_GROUP(read_bytes_sec_max); > + PARSE_THROTTLER_GROUP(write_bytes_sec_max); > + PARSE_THROTTLER_GROUP(total_iops_sec_max); > + PARSE_THROTTLER_GROUP(read_iops_sec_max); > + PARSE_THROTTLER_GROUP(write_iops_sec_max); > + > + PARSE_THROTTLER_GROUP(size_iops_sec); > + > + PARSE_THROTTLER_GROUP(total_bytes_sec_max_length); > + PARSE_THROTTLER_GROUP(read_bytes_sec_max_length); > + PARSE_THROTTLER_GROUP(write_bytes_sec_max_length); > + PARSE_THROTTLER_GROUP(total_iops_sec_max_length); > + PARSE_THROTTLER_GROUP(read_iops_sec_max_length); > + PARSE_THROTTLER_GROUP(write_iops_sec_max_length); > + } > + > + /* Serialize the ThrottleGroup parameters. */ > + if (virTypedParamsSerialize(params, nparams, > + REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX, > + (struct _virTypedParameterRemote **) > &ret->params.params_val, > + &ret->params.params_len, > + args->flags) < 0) > + goto cleanup; > + > + rv = 0; > + > + cleanup: > + if (rv < 0) > + virNetMessageSaveError(rerr); > + virTypedParamsFree(params, nparams); > + virObjectUnref(dom); > + return rv; > +} > +#undef PARSE_THROTTLEGROUP > + > + > /*-------------------------------------------------------------*/ > > static int > diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c > index 307f9ca945..a76212a22b 100644 > --- a/src/remote/remote_driver.c > +++ b/src/remote/remote_driver.c > @@ -2582,6 +2582,7 @@ static int remoteDomainGetBlockIoTune(virDomainPtr > domain, > return 0; > } > > + > static int remoteDomainGetCPUStats(virDomainPtr domain, Spurious newline. > virTypedParameterPtr params, > unsigned int nparams, > @@ -7835,6 +7836,8 @@ static virHypervisorDriver hypervisor_driver = { > .domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* > 8.0.0 */ > .domainFDAssociate = remoteDomainFDAssociate, /* 9.0.0 */ > .domainGraphicsReload = remoteDomainGraphicsReload, /* 10.2.0 */ > + .domainSetThrottleGroup = remoteDomainSetThrottleGroup, /* 11.1.0 */ > + .domainDelThrottleGroup = remoteDomainDelThrottleGroup, /* 11.1.0 */ > }; > > static virNetworkDriver network_driver = { > diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x > index 41c045ff78..1d3e8a7a8c 100644 > --- a/src/remote/remote_protocol.x > +++ b/src/remote/remote_protocol.x > @@ -113,6 +113,9 @@ const REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX = 16; > /* Upper limit on list of blockio tuning parameters. */ > const REMOTE_DOMAIN_BLOCK_IO_TUNE_PARAMETERS_MAX = 32; > > +/* Upper limit on list of throttle group parameters. */ > +const REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX = 32; We should be able to reuse the former. > + > /* Upper limit on list of numa parameters. */ > const REMOTE_DOMAIN_NUMA_PARAMETERS_MAX = 16; > > @@ -1475,6 +1478,29 @@ struct remote_domain_get_block_io_tune_ret { > int nparams; > }; > > +struct remote_domain_set_throttle_group_args { > + remote_nonnull_domain dom; > + remote_nonnull_string group; > + remote_typed_param params<REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX>; > + unsigned int flags; > +}; > + > +struct remote_domain_get_throttle_group_args { > + remote_nonnull_domain dom; > + remote_string group; > + unsigned int flags; > +}; > + > +struct remote_domain_get_throttle_group_ret { > + remote_typed_param params<REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX>; > +}; Getter doesn't exist yet you declare RPC for it. > + > +struct remote_domain_del_throttle_group_args { > + remote_nonnull_domain dom; > + remote_string group; > + unsigned int flags; > +}; > + > struct remote_domain_get_cpu_stats_args { > remote_nonnull_domain dom; > unsigned int nparams; > @@ -7048,5 +7074,27 @@ enum remote_procedure { > * @generate: both > * @acl: domain:write > */ > - REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD = 448 > + REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD = 448, > + > + /** > + * @generate: both > + * @acl: domain:write > + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE > + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG > + */ > + REMOTE_PROC_DOMAIN_SET_THROTTLE_GROUP = 449, > + > + /** > + * @generate: none > + * @acl: domain:read > + */ > + REMOTE_PROC_DOMAIN_GET_THROTTLE_GROUP = 450, ... and here too. > + > + /** > + * @generate: both > + * @acl: domain:write > + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE > + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG > + */ > + REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP = 451 > };