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

Wang, Huaqiang huaqiang.wang at intel.com
Wed Nov 14 02:57:14 UTC 2018



> -----Original Message-----
> From: John Ferlan [mailto:jferlan at redhat.com]
> Sent: Wednesday, November 14, 2018 7:57 AM
> To: Wang, Huaqiang <huaqiang.wang at intel.com>; libvir-list at redhat.com
> Cc: Feng, Shaohe <shaohe.feng at intel.com>; Ding, Jian-feng <jian-
> feng.ding at intel.com>; Zang, Rui <rui.zang at intel.com>
> Subject: Re: [PATCHv8 16/17] qemu: Report cache occupancy (CMT) with
> domstats
> 
> 
> 
> 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.

Thanks for mentioning, I haven't realized virsh.pod need a fix.

I will send out a standalone patch for patch16 and adding this fix soon.

> 
> 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
> 

Thanks for your review and all your hard work.
Huaqiang

> >
> > 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