<div dir="ltr">Peter, thanks a lot for the review! I'll come back with fixes.<br><div><br>пт, 29 янв. 2021 г. в 18:25, Peter Krempa <<a href="mailto:pkrempa@redhat.com">pkrempa@redhat.com</a>>:<br>><br>> On Fri, Jan 29, 2021 at 17:34:02 +0300, Aleksei Zakharov wrote:<br>> > This commit adds delay time (steal time inside guest) to libvirt<br>> > domain CPU stats. It's more convenient to work with this statistic<br>> > in a context of libvirt domain. Any monitoring software may use<br>> > this information.<br>><br>> Please primarily describe what the value is used for.<br>><br>> ><br>> > As an example: the next step is to add support to<br>> > libvirt-go and expose metrics with libvirt-exporter.<br>><br>> This doesn't belong to a commit message.<br>><br>> ><br>> > Signed-off-by: Aleksei Zakharov <<a href="mailto:zaharov@selectel.ru">zaharov@selectel.ru</a>><br>> > ---<br>> >  include/libvirt/libvirt-domain.h |  6 ++++<br>> >  src/qemu/qemu_driver.c           | 56 ++++++++++++++++++++++++++++++++<br>> >  tools/virsh-domain.c             |  3 +-<br>> >  3 files changed, 64 insertions(+), 1 deletion(-)<br>> ><br>> > diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h<br>> > index de2456812c..b3f9f375a5 100644<br>> > --- a/include/libvirt/libvirt-domain.h<br>> > +++ b/include/libvirt/libvirt-domain.h<br>> > @@ -1350,6 +1350,12 @@ int                     virDomainGetState       (virDomainPtr domain,<br>> >   */<br>> >  # define VIR_DOMAIN_CPU_STATS_SYSTEMTIME "system_time"<br>> > <br>> > +/**<br>> > + * VIR_DOMAIN_CPU_STATS_DELAYTIME:<br>> > + * cpu time waiting on runqueue in nanoseconds, as a ullong<br>> > + */<br>> > +# define VIR_DOMAIN_CPU_STATS_DELAYTIME "delay_time"<br>> > +<br>> >  /**<br>> >   * VIR_DOMAIN_CPU_STATS_VCPUTIME:<br>> >   * vcpu usage in nanoseconds (cpu_time excluding hypervisor time),<br>> > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c<br>> > index 6193376544..41839a0239 100644<br>> > --- a/src/qemu/qemu_driver.c<br>> > +++ b/src/qemu/qemu_driver.c<br>> > @@ -16674,6 +16674,36 @@ qemuDomainGetMetadata(virDomainPtr dom,<br>> >      return ret;<br>> >  }<br>> > <br>> > +static int<br>> > +virSchedstatGetDelay(virDomainObjPtr dom, unsigned long long *delay)<br>> > +{<br>> > +    char *proc = NULL;<br>> > +    FILE* schedstat;<br>> > +    unsigned long long curr_delay, oncpu = 0;<br>> > +    pid_t pid = dom->pid;<br>> > +    for (size_t i = 0; i < virDomainDefGetVcpusMax(dom->def); i++) {<br>><br>> Wouldn't it be worth co collect the stats per-vcpu?<br>><br>> Also we don't allow variable declaration inside loops.<br>><br>> Additionally virDomainDefGetVcpusMax returns the total number of cpus,<br>> so you'll attempt to gather stats for offline vcpus too, which will fail<br>> because qemu doesn't create cpu threads for them.<br>><br>> > +        pid_t vcpupid = qemuDomainGetVcpuPid(dom, i);<br>> > +        if (vcpupid) {<br>> > +            if (asprintf(&proc, "/proc/%d/task/%d/schedstat",<br>> > +                                    pid, vcpupid) < 0)<br>><br>> Note that we use the glib versions of formatters thus g_strdup_printf<br>> here.<br>><br>> > +                return -1;<br>> > +        } else {<br>> > +            if (asprintf(&proc, "/proc/%d/schedstat", pid) < 0)<br>> > +                return -1;<br>> > +        }<br>> > +        schedstat = fopen(proc, "r");<br>> > +        VIR_FREE(proc);<br>> > +        if (!schedstat ||<br>> > +            fscanf(schedstat, "%llu %llu",<br>> > +                &oncpu, &curr_delay) < 2) {<br>><br>> The alignment here is off and doesn't conform to our coding style<br>><br>> > +                return -1;<br>> > +        }<br>> > +<br>> > +        *delay += curr_delay;<br>> > +    }<br>> > +    return 0;<br>> > +}<br>> > +<br>> > <br>> >  static int<br>> >  qemuDomainGetCPUStats(virDomainPtr domain,<br>> > @@ -16687,6 +16717,7 @@ qemuDomainGetCPUStats(virDomainPtr domain,<br>> >      int ret = -1;<br>> >      qemuDomainObjPrivatePtr priv;<br>> >      virBitmapPtr guestvcpus = NULL;<br>> > +    unsigned long long delay = 0;<br>> > <br>> >      virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);<br>> > <br>> > @@ -16712,8 +16743,19 @@ qemuDomainGetCPUStats(virDomainPtr domain,<br>> >          goto cleanup;<br>> > <br>> >      if (start_cpu == -1)<br>> > +    {<br>><br>> This doesn't conform to our coding style<br>><br>> >          ret = virCgroupGetDomainTotalCpuStats(priv->cgroup,<br>> >                                                params, nparams);<br>> > +        if (nparams > 3) {<br>> > +            if (virSchedstatGetDelay(vm,&delay) < 0)<br>> > +                return -1;<br>> > +            if (virTypedParameterAssign(&params[3],<br>> > +                            VIR_DOMAIN_CPU_STATS_DELAYTIME,<br>> > +                            VIR_TYPED_PARAM_ULLONG, delay) < 0)<br>> > +             return -1;<br>><br>> The alignment is totally off here.<br>><br>> > +        }<br>> > +        ret++;<br>> > +    }<br>><br>> Many of those problems above actually trip our test suite.<br>><br>> Our contributor guidelines specifically ask contributors to run the test<br>> suite before posting patches. Please fix all of the problems and<br>> re-send.<br>><br>><br>> >      else<br>> >          ret = virCgroupGetPercpuStats(priv->cgroup, params, nparams,<br>> >                                        start_cpu, ncpus, guestvcpus);<br>> > @@ -17845,6 +17887,17 @@ qemuDomainGetStatsMemoryBandwidth(virQEMUDriverPtr driver,<br>> >      return ret;<br>> >  }<br>> > <br>> > +static int<br>> > +qemuDomainGetStatsCpuDelay(virDomainObjPtr dom,<br>> > +                           virTypedParamListPtr params)<br>> > +{<br>> > +    unsigned long long delay_time = 0;<br>> > +    int err = 0;<br>> > +    err = virSchedstatGetDelay(dom, &delay_time);<br>><br>> You can return here directly without the need for 'err' variable.<br>><br>> > +    if (!err && virTypedParamListAddULLong(params, delay_time, "cpu.delay") < 0)<br>> > +        return -1;<br>> > +    return 0;<br>> > +}<br>> > <br>> >  static int<br>> >  qemuDomainGetStatsCpuCache(virQEMUDriverPtr driver,<br>><br><br></div></div>