On 01/20/2014 07:12 PM, Thorsten Behrens wrote: > --- > > Notes on v2: > - elided extra memset and leftover loop var n > - api slot comment references 1.2.2 now > > src/lxc/lxc_driver.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 128 insertions(+) > > diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c > index 8cf8e48..19426f5 100644 > --- a/src/lxc/lxc_driver.c > +++ b/src/lxc/lxc_driver.c > @@ -75,6 +75,8 @@ > > > #define LXC_NB_MEM_PARAM 3 > +#define LXC_NB_PER_CPU_STAT_PARAM 1 > + > > static int lxcStateInitialize(bool privileged, > virStateInhibitCallback callback, > @@ -4775,6 +4777,131 @@ cleanup: > } > > > +static int > +lxcDomainGetPercpuStats(virDomainObjPtr vm, > + virTypedParameterPtr params, > + unsigned int nparams, > + int start_cpu, > + unsigned int ncpus) > +{ > + int rv = -1; > + size_t i; > + int id, max_id; > + char *pos; > + char *buf = NULL; > + virLXCDomainObjPrivatePtr priv = vm->privateData; > + virTypedParameterPtr ent; > + int param_idx; > + unsigned long long cpu_time; > + > + /* TODO: share api contract code with other drivers here */ > + > + /* return the number of supported params */ > + if (nparams == 0 && ncpus != 0) > + return LXC_NB_PER_CPU_STAT_PARAM; > + > + /* To parse account file, we need to know how many cpus are present. */ > + max_id = nodeGetCPUCount(); > + if (max_id < 0) > + return rv; > + > + if (ncpus == 0) { /* returns max cpu ID */ > + rv = max_id; > + goto cleanup; > + } > + > + if (start_cpu > max_id) { > + virReportError(VIR_ERR_INVALID_ARG, > + _("start_cpu %d larger than maximum of %d"), > + start_cpu, max_id); > + goto cleanup; > + } > + > + /* we get percpu cputime accounting info. */ > + if (virCgroupGetCpuacctPercpuUsage(priv->cgroup, &buf)) > + goto cleanup; > + pos = buf; > + > + /* return percpu cputime in index 0 */ > + param_idx = 0; > + > + /* number of cpus to compute */ > + if (start_cpu >= max_id - ncpus) > + id = max_id - 1; > + else > + id = start_cpu + ncpus - 1; > + > + for (i = 0; i <= id; i++) { > + if (virStrToLong_ull(pos, &pos, 10, &cpu_time) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("cpuacct parse error")); > + goto cleanup; > + } > + if (i < start_cpu) > + continue; > + ent = ¶ms[(i - start_cpu) * nparams + param_idx]; > + if (virTypedParameterAssign(ent, VIR_DOMAIN_CPU_STATS_CPUTIME, > + VIR_TYPED_PARAM_ULLONG, cpu_time) < 0) > + goto cleanup; > + } > + > + rv = nparams; > + > +cleanup: > + VIR_FREE(buf); > + return rv; > +} > + > + > +static int > +lxcDomainGetCPUStats(virDomainPtr dom, > + virTypedParameterPtr params, > + unsigned int nparams, > + int start_cpu, > + unsigned int ncpus, > + unsigned int flags) > +{ > + virDomainObjPtr vm = NULL; > + int ret = -1; > + bool isActive; > + virLXCDomainObjPrivatePtr priv; > + > + virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1); > + > + if (!(vm = lxcDomObjFromDomain(dom))) > + return ret; > + > + priv = vm->privateData; > + > + if (virDomainGetCPUStatsEnsureACL(dom->conn, vm->def) < 0) > + goto cleanup; > + > + isActive = virDomainObjIsActive(vm); > + if (!isActive) { > + virReportError(VIR_ERR_OPERATION_INVALID, "%s", > + _("domain is not running")); > + goto cleanup; > + } > + > + if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUACCT)) { > + virReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("cgroup CPUACCT controller is not mounted")); > + goto cleanup; > + } > + > + if (start_cpu == -1) > + ret = virCgroupGetDomainTotalCpuStats(priv->cgroup, > + params, nparams); > + else > + ret = lxcDomainGetPercpuStats(vm, params, nparams, > + start_cpu, ncpus); > +cleanup: > + if (vm) > + virObjectUnlock(vm); > + return ret; > +} > + > + > /* Function Tables */ > static virDriver lxcDriver = { > .no = VIR_DRV_LXC, > @@ -4852,6 +4979,7 @@ static virDriver lxcDriver = { > .nodeSuspendForDuration = lxcNodeSuspendForDuration, /* 0.9.8 */ > .domainSetMetadata = lxcDomainSetMetadata, /* 1.1.3 */ > .domainGetMetadata = lxcDomainGetMetadata, /* 1.1.3 */ > + .domainGetCPUStats = lxcDomainGetCPUStats, /* 1.2.2 */ > .nodeGetMemoryParameters = lxcNodeGetMemoryParameters, /* 0.10.2 */ > .nodeSetMemoryParameters = lxcNodeSetMemoryParameters, /* 0.10.2 */ > .domainSendProcessSignal = lxcDomainSendProcessSignal, /* 1.0.1 */ > Looks good to me ACK thanks! -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list