[libvirt] [PATCHv8 16/17] qemu: Report cache occupancy (CMT) with domstats

John Ferlan jferlan at redhat.com
Tue Nov 13 23:56:30 UTC 2018



On 11/12/18 8:31 AM, Wang Huaqiang wrote:
> Adding the interface in qemu to report CMT statistic information
> through command 'virsh domstats --cpu-total'.

I believe virsh.pod needs an update to list this type of data in the
domstats --cpu-total output.

In any case, I need to drop off for the evening - I'll pick this up in
the morning. You can send an update to this patch and I can merge it in.

The first 15 patches look good with some minor adjustments...

John

> 
> Below is a typical output:
> 
>          # virsh domstats 1 --cpu-total
>          Domain: 'ubuntu16.04-base'
>            ...
>            cpu.cache.monitor.count=2
>            cpu.cache.monitor.0.name=vcpus_1
>            cpu.cache.monitor.0.vcpus=1
>            cpu.cache.monitor.0.bank.count=2
>            cpu.cache.monitor.0.bank.0.id=0
>            cpu.cache.monitor.0.bank.0.bytes=4505600
>            cpu.cache.monitor.0.bank.1.id=1
>            cpu.cache.monitor.0.bank.1.bytes=5586944
>            cpu.cache.monitor.1.name=vcpus_4-6
>            cpu.cache.monitor.1.vcpus=4,5,6
>            cpu.cache.monitor.1.bank.count=2
>            cpu.cache.monitor.1.bank.0.id=0
>            cpu.cache.monitor.1.bank.0.bytes=17571840
>            cpu.cache.monitor.1.bank.1.id=1
>            cpu.cache.monitor.1.bank.1.bytes=29106176
> 
> Signed-off-by: Wang Huaqiang <huaqiang.wang at intel.com>
> ---
>  src/libvirt-domain.c   |   9 +++
>  src/qemu/qemu_driver.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 207 insertions(+)
> 
> diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
> index 7690339..4895f9f 100644
> --- a/src/libvirt-domain.c
> +++ b/src/libvirt-domain.c
> @@ -11345,6 +11345,15 @@ virConnectGetDomainCapabilities(virConnectPtr conn,
>   *     "cpu.user" - user cpu time spent in nanoseconds as unsigned long long.
>   *     "cpu.system" - system cpu time spent in nanoseconds as unsigned long
>   *                    long.
> + *     "cpu.cache.monitor.count" - tocal cache monitoring groups
> + *     "cpu.cache.monitor.M.name" - name of cache monitoring group 'M'
> + *     "cpu.cache.monitor.M.vcpus" - vcpus for cache monitoring group 'M'
> + *     "cpu.cache.monitor.M.bank.count" - total bank number of cache monitoring
> + *                    group 'M'
> + *     "cpu.cache.monitor.M.bank.N.id" - OS assigned cache bank id for cache
> + *                    'N' in cache monitoring group 'M'
> + *     "cpu.cache.monitor.M.bank.N.bytes" - monitor's cache occupancy of cache
> + *                    bank 'N' in cache monitoring group 'M'
>   *
>   * VIR_DOMAIN_STATS_BALLOON:
>   *     Return memory balloon device information.
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 89d46ee..d41ae66 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -19698,6 +19698,199 @@ typedef enum {
>  #define HAVE_JOB(flags) ((flags) & QEMU_DOMAIN_STATS_HAVE_JOB)
>  
>  
> +typedef struct _virQEMUCpuResMonitorData virQEMUCpuResMonitorData;
> +typedef virQEMUCpuResMonitorData *virQEMUCpuResMonitorDataPtr;
> +struct _virQEMUCpuResMonitorData{

Data {

> +    const char *name;
> +    char *vcpus;
> +    virResctrlMonitorType tag;
> +    virResctrlMonitorStatsPtr stats;
> +    size_t nstats;
> +};
> +
> +
> +static int
> +qemuDomainGetCpuResMonitorData(virDomainObjPtr dom,
> +                               virQEMUCpuResMonitorDataPtr mondata)
> +{
> +    virDomainResctrlDefPtr resctrl = NULL;
> +    size_t i = 0;
> +    size_t j = 0;
> +    size_t l = 0;
> +
> +    for (i = 0; i < dom->def->nresctrls; i++) {
> +        resctrl = dom->def->resctrls[i];
> +
> +        for (j = 0; j < resctrl->nmonitors; j++) {
> +            virDomainResctrlMonDefPtr domresmon = NULL;
> +            virResctrlMonitorPtr monitor = resctrl->monitors[j]->instance;
> +
> +            domresmon = resctrl->monitors[j];
> +            mondata[l].tag = domresmon->tag;
> +
> +            /* If virBitmapFormat successfully returns an vcpu string, then
> +             * mondata[l].vcpus is assigned with an memory space holding it,
> +             * let this newly allocated memory buffer to be freed along with
> +             * the free of 'mondata' */
> +            if (!(mondata[l].vcpus = virBitmapFormat(domresmon->vcpus)))
> +                return -1;
> +
> +            if (!(mondata[l].name = virResctrlMonitorGetID(monitor))) {
> +                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                               _("Could not get monitor ID"));
> +                return -1;
> +            }
> +
> +            if (domresmon->tag == VIR_RESCTRL_MONITOR_TYPE_CACHE) {
> +                if (virResctrlMonitorGetCacheOccupancy(monitor,
> +                                                       &mondata[l].stats,
> +                                                       &mondata[l].nstats) < 0)
> +                    return -1;
> +            } else {
> +                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                               _("Invalid CPU resource type"));
> +                return -1;
> +            }
> +
> +            l++;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +
> +static int
> +qemuDomainGetStatsCpuResMonitorPerTag(virQEMUCpuResMonitorDataPtr mondata,
> +                                      size_t nmondata,
> +                                      virResctrlMonitorType tag,
> +                                      virDomainStatsRecordPtr record,
> +                                      int *maxparams)
> +{
> +    char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
> +    unsigned int nmonitors = 0;
> +    const char *resname = NULL;
> +    const char *resnodename = NULL;
> +    size_t i = 0;
> +
> +    for (i = 0; i < nmondata; i++) {
> +        if (mondata[i].tag == tag)
> +            nmonitors++;
> +    }
> +
> +    if (!nmonitors)
> +        return 0;
> +
> +    if (tag == VIR_RESCTRL_MONITOR_TYPE_CACHE) {
> +        resname = "cache";
> +        resnodename = "bank";
> +    } else if (tag == VIR_RESCTRL_MONITOR_TYPE_MEMBW) {
> +        resname = "memBW";
> +        resnodename = "node";
> +    } else {
> +        return 0;
> +    }
> +
> +    snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
> +             "cpu.%s.monitor.count", resname);
> +    if (virTypedParamsAddUInt(&record->params, &record->nparams,
> +                              maxparams, param_name, nmonitors) < 0)
> +        return -1;
> +
> +    for (i = 0; i < nmonitors; i++) {
> +        size_t l = 0;
> +
> +        snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
> +                 "cpu.%s.monitor.%zd.name", resname, i);
> +        if (virTypedParamsAddString(&record->params,
> +                                    &record->nparams,
> +                                    maxparams,
> +                                    param_name,
> +                                    mondata[i].name) < 0)
> +            return -1;
> +
> +        snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
> +                 "cpu.%s.monitor.%zd.vcpus", resname, i);
> +        if (virTypedParamsAddString(&record->params, &record->nparams,
> +                                    maxparams, param_name,
> +                                    mondata[i].vcpus) < 0)
> +            return -1;
> +
> +        snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
> +                 "cpu.%s.monitor.%zd.%s.count", resname, i, resnodename);
> +        if (virTypedParamsAddUInt(&record->params, &record->nparams,
> +                                  maxparams, param_name,
> +                                  mondata[i].nstats) < 0)
> +            return -1;
> +
> +        for (l = 0; l < mondata[i].nstats; l++) {
> +            snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
> +                     "cpu.%s.monitor.%zd.%s.%zd.id",
> +                     resname, i, resnodename, l);
> +            if (virTypedParamsAddUInt(&record->params, &record->nparams,
> +                                      maxparams, param_name,
> +                                      mondata[i].stats[l].id) < 0)
> +                return -1;
> +
> +            snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
> +                     "cpu.%s.monitor.%zd.%s.%zd.bytes",
> +                     resname, i, resnodename, l);
> +            if (virTypedParamsAddUInt(&record->params, &record->nparams,
> +                                      maxparams, param_name,
> +                                      mondata[i].stats[l].val) < 0)
> +                return -1;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +
> +static int
> +qemuDomainGetStatsCpuResMonitor(virDomainObjPtr dom,
> +                                virDomainStatsRecordPtr record,
> +                                int *maxparams)
> +{
> +    virDomainResctrlDefPtr resctrl = NULL;
> +    virQEMUCpuResMonitorDataPtr mondata = NULL;
> +    unsigned int nmonitors = 0;
> +    size_t i = 0;
> +    int ret = -1;
> +
> +    if (!virDomainObjIsActive(dom))
> +        return 0;
> +
> +    for (i = 0; i < dom->def->nresctrls; i++) {
> +        resctrl = dom->def->resctrls[i];
> +        nmonitors += resctrl->nmonitors;
> +    }
> +
> +    if (!nmonitors)
> +        return 0;
> +
> +    if (VIR_ALLOC_N(mondata, nmonitors) < 0)
> +        return -1;
> +
> +    if (qemuDomainGetCpuResMonitorData(dom, mondata) < 0)
> +        goto cleanup;
> +
> +    for (i = VIR_RESCTRL_MONITOR_TYPE_UNSUPPORT + 1;
> +         i < VIR_RESCTRL_MONITOR_TYPE_LAST; i++) {
> +        if (qemuDomainGetStatsCpuResMonitorPerTag(mondata, nmonitors, i,
> +                                                  record, maxparams) < 0)
> +            goto cleanup;
> +    }
> +
> +    ret = 0;
> + cleanup:
> +    for (i = 0; i < nmonitors; i++)
> +        VIR_FREE(mondata[i].vcpus);
> +    VIR_FREE(mondata);
> +
> +    return ret;
> +}
> +
> +
>  static int
>  qemuDomainGetStatsCpuCgroup(virDomainObjPtr dom,
>                              virDomainStatsRecordPtr record,
> @@ -19747,6 +19940,11 @@ qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
>  {
>      if (qemuDomainGetStatsCpuCgroup(dom, record, maxparams) < 0)
>          return -1;
> +
> +    if (qemuDomainGetStatsCpuResMonitor(dom, record, maxparams) < 0)
> +        return -1;
> +
> +    return 0;
>  }
>  
>  
> 




More information about the libvir-list mailing list