[libvirt] [PATCH v2 0/6] lxc: Add suport to virConnectGetAllDomainStats

This series has a collection of new methods to enable support for virConnectGetAllDomainStats() to LXC driver. The only difference is Disk Stats. It needs to consider only the host file system operations as a valid block device. So, other disks should start with index 1..N. Other difference is an implementation of Kernel Memory CGroup to grab this info from each LXC container. - v1-v2: Added suggestions made by Peter Krempa. Julio Faracco (6): lxc: Introduce method lxcConnectGetAllDomainStats lxc: Introduce method lxcDomainGetStats lxc: Introduce method lxcDomainGetStatsCpu lxc: Introduce method lxcDomainGetStatsBlock cgroup: Get kernel memory entry from CGroup V1 lxc: Introduce method lxcDomainGetBalloonStats src/libvirt_private.syms | 2 + src/lxc/lxc_driver.c | 391 ++++++++++++++++++++++++++++++++++++ src/util/vircgroup.c | 32 +++ src/util/vircgroup.h | 2 + src/util/vircgroupbackend.h | 10 + src/util/vircgroupv1.c | 36 ++++ 6 files changed, 473 insertions(+) -- 2.19.1

This is an implementation of method used by driver to retrieve stats from all domain. Right now, this is a simple implementation considering only State, CPU, Disks and Balloon. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_driver.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index e981f8e901..8c545fc602 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -5271,6 +5271,71 @@ lxcDomainGetMetadata(virDomainPtr dom, } +static int +lxcConnectGetAllDomainStats(virConnectPtr conn, + virDomainPtr *doms, + unsigned int ndoms, + unsigned int stats, + virDomainStatsRecordPtr **retStats, + unsigned int flags) +{ + virLXCDriverPtr driver = conn->privateData; + virDomainObjPtr *vms = NULL; + size_t nvms; + virDomainStatsRecordPtr *tmpstats = NULL; + int nstats = 0; + int ret = -1; + unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE | + VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT | + VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE); + unsigned int supported = VIR_DOMAIN_STATS_STATE | + VIR_DOMAIN_STATS_CPU_TOTAL | + VIR_DOMAIN_STATS_BLOCK | + VIR_DOMAIN_STATS_BALLOON; + + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE | + VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT | + VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE | + VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, -1); + + if (virConnectGetAllDomainStatsEnsureACL(conn) < 0) + return -1; + + if (!stats) { + stats = supported; + } else if ((flags & VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS) && + (stats & ~supported)) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, + _("Stats types bits 0x%x are not supported by this daemon"), + stats & ~supported); + return -1; + } + + if (ndoms) { + if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms, + &nvms, virConnectGetAllDomainStatsCheckACL, + lflags, true) < 0) + return -1; + } else { + if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms, + virConnectGetAllDomainStatsCheckACL, + lflags) < 0) + return -1; + } + + if (VIR_ALLOC_N(tmpstats, ndoms + 1) < 0) + goto cleanup; + + VIR_STEAL_PTR(*retStats, tmpstats); + ret = nstats; + + cleanup: + virDomainStatsRecordListFree(tmpstats); + virObjectListFreeCount(vms, nvms); + + return ret; +} + static int lxcDomainGetCPUStats(virDomainPtr dom, virTypedParameterPtr params, @@ -5441,6 +5506,7 @@ static virHypervisorDriver lxcHypervisorDriver = { .domainMemoryStats = lxcDomainMemoryStats, /* 1.2.2 */ .nodeGetCPUStats = lxcNodeGetCPUStats, /* 0.9.3 */ .nodeGetMemoryStats = lxcNodeGetMemoryStats, /* 0.9.3 */ + .connectGetAllDomainStats = lxcConnectGetAllDomainStats, /* 5.2.0 */ .nodeGetCellsFreeMemory = lxcNodeGetCellsFreeMemory, /* 0.6.5 */ .nodeGetFreeMemory = lxcNodeGetFreeMemory, /* 0.6.5 */ .nodeGetCPUMap = lxcNodeGetCPUMap, /* 1.0.0 */ -- 2.19.1

This method is responsible to fetch data like State, CPU, Disk and Balloon info (all single domain info) from each domain 'virDomainObjPtr'. There is an implementation of method lxcDomainGetStatsState() to give a small functionality to lxcDomainGetStats(). Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_driver.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 8c545fc602..be26cf18a4 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -5271,6 +5271,69 @@ lxcDomainGetMetadata(virDomainPtr dom, } +static int +lxcDomainGetStatsState(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams, + unsigned int supported) +{ + unsigned int flags = VIR_DOMAIN_STATS_STATE; + + virCheckFlags(supported, 0); + + if (virTypedParamsAddInt(&record->params, + &record->nparams, + maxparams, + "state.state", + dom->state.state) < 0) + return -1; + + if (virTypedParamsAddInt(&record->params, + &record->nparams, + maxparams, + "state.reason", + dom->state.reason) < 0) + return -1; + + return 0; +} + + +static virDomainStatsRecordPtr +lxcDomainGetStats(virConnectPtr conn, + virDomainObjPtr dom, + unsigned int flags) +{ + virLXCDriverPtr driver = conn->privateData; + virDomainStatsRecordPtr stat; + int maxparams = 0; + + if (VIR_ALLOC(stat) < 0) + return NULL; + + if (!(stat->dom = virGetDomain(conn, dom->def->name, dom->def->uuid, dom->def->id))) + goto error; + + if (virLXCDomainObjBeginJob(driver, dom, LXC_JOB_QUERY) < 0) + goto error; + + if (lxcDomainGetStatsState(dom, stat, &maxparams, flags) < 0) + goto endjob; + + virLXCDomainObjEndJob(driver, dom); + return stat; + + endjob: + virLXCDomainObjEndJob(driver, dom); + + error: + virTypedParamsFree(stat->params, stat->nparams); + virObjectUnref(stat->dom); + VIR_FREE(stat); + return NULL; +} + + static int lxcConnectGetAllDomainStats(virConnectPtr conn, virDomainPtr *doms, @@ -5281,7 +5344,9 @@ lxcConnectGetAllDomainStats(virConnectPtr conn, { virLXCDriverPtr driver = conn->privateData; virDomainObjPtr *vms = NULL; + virDomainObjPtr vm; size_t nvms; + size_t i; virDomainStatsRecordPtr *tmpstats = NULL; int nstats = 0; int ret = -1; @@ -5326,6 +5391,21 @@ lxcConnectGetAllDomainStats(virConnectPtr conn, if (VIR_ALLOC_N(tmpstats, ndoms + 1) < 0) goto cleanup; + for (i = 0; i < nvms; i++) { + virDomainStatsRecordPtr tmp; + vm = vms[i]; + + virObjectLock(vm); + tmp = lxcDomainGetStats(conn, vm, stats); + virObjectUnlock(vm); + + if (!tmp) + goto cleanup; + + tmpstats[nstats++] = tmp; + + } + VIR_STEAL_PTR(*retStats, tmpstats); ret = nstats; -- 2.19.1

This method is responsible to fetch all CPU Cgroup Stats and store data into virDomainStatsRecordPtr structure. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_driver.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index be26cf18a4..0e6d5743d0 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -5299,6 +5299,53 @@ lxcDomainGetStatsState(virDomainObjPtr dom, } +static int +lxcDomainGetStatsCpu(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams, + unsigned int supported) +{ + virLXCDomainObjPrivatePtr priv = dom->privateData; + unsigned long long cpu_time = 0; + unsigned long long user_time = 0; + unsigned long long sys_time = 0; + unsigned int flags = VIR_DOMAIN_STATS_CPU_TOTAL; + int err = 0; + + virCheckFlags(supported, 0); + + if (virDomainObjCheckActive(dom) < 0) + return 0; + + if (!priv->cgroup) + return 0; + + err = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time); + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.time", + cpu_time) < 0) + return -1; + + err = virCgroupGetCpuacctStat(priv->cgroup, &user_time, &sys_time); + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.user", + user_time) < 0) + return -1; + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.system", + sys_time) < 0) + return -1; + + return 0; +} + + static virDomainStatsRecordPtr lxcDomainGetStats(virConnectPtr conn, virDomainObjPtr dom, @@ -5320,6 +5367,9 @@ lxcDomainGetStats(virConnectPtr conn, if (lxcDomainGetStatsState(dom, stat, &maxparams, flags) < 0) goto endjob; + if (lxcDomainGetStatsCpu(dom, stat, &maxparams, flags) < 0) + goto endjob; + virLXCDomainObjEndJob(driver, dom); return stat; -- 2.19.1

This method is responsible to fetch all Block Cgroup Stats and store data into virDomainStatsRecordPtr structure. This particular method check three other information like capacity, allocation and physical space. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_driver.c | 130 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 0e6d5743d0..a83837077d 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2476,6 +2476,133 @@ lxcDomainBlockStatsFlags(virDomainPtr dom, } +static int +lxcDomainGetStatsBlock(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams, + unsigned int supported) +{ + virLXCDomainObjPrivatePtr priv = dom->privateData; + virDomainBlockStatsStruct stats; + size_t i = 0, index = 0; + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; + unsigned int flags = VIR_DOMAIN_STATS_BLOCK; + + virCheckFlags(supported, 0); + + if (virDomainObjCheckActive(dom) < 0) + return 0; + + if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("blkio cgroup isn't mounted")); + return -1; + } + +#define LXC_ADD_STAT_PARAM_UUL(group, field, subparam) \ +do { \ + if (stats.field != -1) { \ + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ + group ".%zu." subparam, index); \ + if (virTypedParamsAddULLong(&record->params, \ + &record->nparams, \ + maxparams, \ + param_name, \ + stats.field) < 0) \ + return -1; \ + } \ +} while (0) + + if (virCgroupGetBlkioIoServiced(priv->cgroup, + &stats.rd_bytes, + &stats.wr_bytes, + &stats.rd_req, + &stats.wr_req) < 0) + return -1; + + LXC_ADD_STAT_PARAM_UUL("block", rd_req, "rd.reqs"); + LXC_ADD_STAT_PARAM_UUL("block", rd_bytes, "rd.bytes"); + LXC_ADD_STAT_PARAM_UUL("block", wr_req, "wr.reqs"); + LXC_ADD_STAT_PARAM_UUL("block", wr_bytes, "wr.bytes"); + + index++; + + for (i = 0; i < dom->def->ndisks; i++) { + virDomainDiskDefPtr disk = dom->def->disks[i]; + + if (*disk->src->path) { + if (!disk->info.alias) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing disk device alias name for %s"), disk->dst); + return -1; + } + + if (virCgroupGetBlkioIoDeviceServiced(priv->cgroup, + disk->info.alias, + &stats.rd_bytes, + &stats.wr_bytes, + &stats.rd_req, + &stats.wr_req) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("domain stats query failed")); + return -1; + } + } + + LXC_ADD_STAT_PARAM_UUL("block", rd_req, "rd.reqs"); + LXC_ADD_STAT_PARAM_UUL("block", rd_bytes, "rd.bytes"); + LXC_ADD_STAT_PARAM_UUL("block", wr_req, "wr.reqs"); + LXC_ADD_STAT_PARAM_UUL("block", wr_bytes, "wr.bytes"); + + if (disk->src->allocation) { + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "block.%zu.allocation", index); + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + param_name, + disk->src->allocation) < 0) + return -1; + } + + if (disk->src->physical) { + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "block.%zu.physical", index); + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + param_name, + disk->src->physical) < 0) + return -1; + } + + if (disk->src->capacity) { + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, + "block.%zu.capacity", i); + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + param_name, + disk->src->capacity) < 0) + return -1; + } + + index++; + } + +#undef LXC_ADD_STAT_PARAM_UUL + + if (virTypedParamsAddUInt(&record->params, + &record->nparams, + maxparams, + "block.count", + index) < 0) + return -1; + + return 0; +} + + static int lxcDomainSetBlkioParameters(virDomainPtr dom, virTypedParameterPtr params, @@ -5370,6 +5497,9 @@ lxcDomainGetStats(virConnectPtr conn, if (lxcDomainGetStatsCpu(dom, stat, &maxparams, flags) < 0) goto endjob; + if (lxcDomainGetStatsBlock(dom, stat, &maxparams, flags) < 0) + goto endjob; + virLXCDomainObjEndJob(driver, dom); return stat; -- 2.19.1

This commit implements two methods to get kernel memory using CGroup V1. One of them get the Hard Limit of kernel memory and the other one get the current kernel memory usage from that current container. For V2, it will return error because it is not defined. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/libvirt_private.syms | 2 ++ src/util/vircgroup.c | 32 ++++++++++++++++++++++++++++++++ src/util/vircgroup.h | 2 ++ src/util/vircgroupbackend.h | 10 ++++++++++ src/util/vircgroupv1.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 212adf53c1..0c2328de0e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1584,6 +1584,8 @@ virCgroupGetMemoryStat; virCgroupGetMemoryUsage; virCgroupGetMemSwapHardLimit; virCgroupGetMemSwapUsage; +virCgroupGetKMemHardLimit; +virCgroupGetKMemUsage; virCgroupGetPercpuStats; virCgroupHasController; virCgroupHasEmptyTasks; diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 34c970f292..2712ae32e6 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -1784,6 +1784,38 @@ virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb) } +/** + * virCgroupGetKMemHardLimit: + * + * @group: The cgroup to get mem+kmem hard limit for + * @kb: The mem+kmem amount in kilobytes + * + * Returns: 0 on success + */ +int +virCgroupGetKMemHardLimit(virCgroupPtr group, unsigned long long *kb) +{ + VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY, + getKMemHardLimit, -1, kb); +} + + +/** + * virCgroupGetKMemUsage: + * + * @group: The cgroup to get mem+kmem usage for + * @kb: The mem+kmem amount in kilobytes + * + * Returns: 0 on success + */ +int +virCgroupGetKMemUsage(virCgroupPtr group, unsigned long long *kb) +{ + VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY, + getKMemUsage, -1, kb); +} + + /** * virCgroupSetCpusetMems: * diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index 372009de4a..edd13742d2 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -191,6 +191,8 @@ int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb); int virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb); int virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb); int virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb); +int virCgroupGetKMemHardLimit(virCgroupPtr group, unsigned long long *kb); +int virCgroupGetKMemUsage(virCgroupPtr group, unsigned long long *kb); enum { VIR_CGROUP_DEVICE_READ = 1, diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h index 24b45be9bb..db4369325b 100644 --- a/src/util/vircgroupbackend.h +++ b/src/util/vircgroupbackend.h @@ -263,6 +263,14 @@ typedef int (*virCgroupGetMemSwapUsageCB)(virCgroupPtr group, unsigned long long *kb); +typedef int +(*virCgroupGetKMemHardLimitCB)(virCgroupPtr group, + unsigned long long *kb); + +typedef int +(*virCgroupGetKMemUsageCB)(virCgroupPtr group, + unsigned long long *kb); + typedef int (*virCgroupAllowDeviceCB)(virCgroupPtr group, char type, @@ -406,6 +414,8 @@ struct _virCgroupBackend { virCgroupSetMemSwapHardLimitCB setMemSwapHardLimit; virCgroupGetMemSwapHardLimitCB getMemSwapHardLimit; virCgroupGetMemSwapUsageCB getMemSwapUsage; + virCgroupGetKMemHardLimitCB getKMemHardLimit; + virCgroupGetKMemUsageCB getKMemUsage; virCgroupAllowDeviceCB allowDevice; virCgroupDenyDeviceCB denyDevice; diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c index c172eb8b96..268088ff0c 100644 --- a/src/util/vircgroupv1.c +++ b/src/util/vircgroupv1.c @@ -1690,6 +1690,40 @@ virCgroupV1GetMemSwapUsage(virCgroupPtr group, } +static int +virCgroupV1GetKMemHardLimit(virCgroupPtr group, + unsigned long long *kb) +{ + long long unsigned int limit_in_bytes; + + if (virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + "memory.kmem.limit_in_bytes", &limit_in_bytes) < 0) + return -1; + + *kb = limit_in_bytes >> 10; + if (*kb >= virCgroupV1GetMemoryUnlimitedKB()) + *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED; + + return 0; +} + + +static int +virCgroupV1GetKMemUsage(virCgroupPtr group, + unsigned long long *kb) +{ + long long unsigned int usage_in_bytes; + int ret; + ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + "memory.kmem.usage_in_bytes", &usage_in_bytes); + if (ret == 0) + *kb = usage_in_bytes >> 10; + return ret; +} + + static int virCgroupV1AllowDevice(virCgroupPtr group, char type, @@ -2085,6 +2119,8 @@ virCgroupBackend virCgroupV1Backend = { .setMemSwapHardLimit = virCgroupV1SetMemSwapHardLimit, .getMemSwapHardLimit = virCgroupV1GetMemSwapHardLimit, .getMemSwapUsage = virCgroupV1GetMemSwapUsage, + .getKMemHardLimit = virCgroupV1GetKMemHardLimit, + .getKMemUsage = virCgroupV1GetKMemUsage, .allowDevice = virCgroupV1AllowDevice, .denyDevice = virCgroupV1DenyDevice, -- 2.19.1

On Mon, Apr 08, 2019 at 04:38:58PM -0300, Julio Faracco wrote:
This commit implements two methods to get kernel memory using CGroup V1. One of them get the Hard Limit of kernel memory and the other one get the current kernel memory usage from that current container. For V2, it will return error because it is not defined.
What is the usage of kmem with relation to memory ballooning? In addition I don't like to introduce new feature that is available only with cgroups V1 as V2 will eventually replace V1 and this feature will be useless. Pavel

This method is responsible to fetch all Balloon Memory Stats and store data into virDomainStatsRecordPtr structure. It contains kernel memory used by current container. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_driver.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index a83837077d..286b5609ee 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2897,6 +2897,68 @@ lxcDomainGetBlkioParameters(virDomainPtr dom, } +static int +lxcDomainGetStatsMemory(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams, + unsigned int supported) +{ + virLXCDomainObjPrivatePtr priv = dom->privateData; + unsigned long long swap_usage; + unsigned long long kmem_usage; + unsigned long mem_usage; + unsigned int flags = VIR_DOMAIN_STATS_BALLOON; + + virCheckFlags(supported, 0); + + if (virDomainObjCheckActive(dom) < 0) + return 0; + + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "balloon.current", + dom->def->mem.cur_balloon) < 0) + return -1; + + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "balloon.maximum", + virDomainDefGetMemoryTotal(dom->def)) < 0) + return -1; + + if (virCgroupGetMemoryUsage(priv->cgroup, &mem_usage) >= 0) { + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "balloon.rss", + mem_usage) < 0) + return -1; + } + + if (virCgroupGetKMemUsage(priv->cgroup, &kmem_usage) >= 0) { + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "balloon.kmem", + kmem_usage) < 0) + return -1; + } + + if (virCgroupGetMemSwapUsage(priv->cgroup, &swap_usage) >= 0) { + if (virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "balloon.swap_in", + swap_usage) < 0) + return -1; + } + + return 0; +} + + static int lxcDomainInterfaceStats(virDomainPtr dom, const char *device, @@ -5500,6 +5562,9 @@ lxcDomainGetStats(virConnectPtr conn, if (lxcDomainGetStatsBlock(dom, stat, &maxparams, flags) < 0) goto endjob; + if (lxcDomainGetStatsMemory(dom, stat, &maxparams, flags) < 0) + goto endjob; + virLXCDomainObjEndJob(driver, dom); return stat; -- 2.19.1
participants (2)
-
Julio Faracco
-
Pavel Hrdina