args->flags) < 0)
goto cleanup;
- percpu_len = ret->params.params_len / args->ncpus;
-
success:
rv = 0;
ret->nparams = percpu_len;
+ if (args->nparams && !(args->flags & VIR_TYPED_PARAM_STRING_OKAY)) {
+ int i;
+
+ for (i = 0; i < percpu_len; i++) {
+ if (params[i].type == VIR_TYPED_PARAM_STRING)
+ ret->nparams--;
+ }
+ }
cleanup:
if (rv < 0)
* whole). Otherwise, @start_cpu represents which cpu to start
* with, and @ncpus represents how many consecutive processors to
* query, with statistics attributable per processor (such as
- * per-cpu usage).
+ * per-cpu usage). If @ncpus is larger than the number of cpus
+ * available to query, then the trailing part of the array will
+ * be unpopulated.
*
* The remote driver imposes a limit of 128 @ncpus and 16 @nparams;
* the number of parameters per cpu should not exceed 16, but if you
* number of populated @params, unless @ncpus was 1; and may be
* less than @nparams). The populated parameters start at each
* stride of @nparams, which means the results may be discontiguous;
- * any unpopulated parameters will be zeroed on success. The caller
- * is responsible for freeing any returned string parameters.
+ * any unpopulated parameters will be zeroed on success (this includes
+ * skipped elements if @nparams is too large, and tail elements if
+ * @ncpus is too large). The caller is responsible for freeing any
+ * returned string parameters.
*/
int virDomainGetCPUStats(virDomainPtr domain,
virTypedParameterPtr params,
if (virCgroupGetCpuacctPercpuUsage(group, &buf))
goto cleanup;
pos = buf;
+ memset(params, 0, nparams * ncpus);
if (max_id - start_cpu > ncpus - 1)
max_id = start_cpu + ncpus - 1;
/* Check the length of the returned list carefully. */
if (ret.params.params_len > nparams * ncpus ||
(ret.params.params_len &&
- ret.nparams * ncpus != ret.params.params_len)) {
+ ((ret.params.params_len % ret.nparams) || ret.nparams > nparams))) {
remoteError(VIR_ERR_RPC, "%s",
_("remoteDomainGetCPUStats: "
"returned number of stats exceeds limit"));
}
/* The remote side did not send back any zero entries, so we have
- * to expand things back into a possibly sparse array.
+ * to expand things back into a possibly sparse array, where the
+ * tail of the array may be omitted.
*/
memset(params, 0, sizeof(*params) * nparams * ncpus);
+ ncpus = ret.params.params_len / ret.nparams;
for (cpu = 0; cpu < ncpus; cpu++) {
int tmp = nparams;
remote_typed_param *stride = &ret.params.params_val[cpu * ret.nparams];