From 40857b9de3714b3314f5c22e924d5993c458acbe Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 24 Jul 2024 15:23:11 +0200 Subject: [PATCH 1/7] tools: lxc-top: refactor lxc-top stat structs Create separate structs for each controller class. This will make it easier to add cgroupv2 support. No functional changes. Signed-off-by: Natanael Copa --- src/lxc/tools/lxc_top.c | 125 +++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 53 deletions(-) diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index aa6e7209e..bcc695b3e 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -35,16 +35,24 @@ struct blkio_stats { uint64_t total; }; -struct stats { - uint64_t mem_used; - uint64_t mem_limit; - uint64_t memsw_used; - uint64_t memsw_limit; +struct cpu_stats { + uint64_t use_nanos; + uint64_t use_user; + uint64_t use_sys; +}; + +struct mem_stats { + uint64_t used; + uint64_t limit; + uint64_t swap_used; + uint64_t swap_limit; uint64_t kmem_used; uint64_t kmem_limit; - uint64_t cpu_use_nanos; - uint64_t cpu_use_user; - uint64_t cpu_use_sys; +}; + +struct stats { + struct mem_stats mem; + struct cpu_stats cpu; struct blkio_stats io_service_bytes; struct blkio_stats io_serviced; }; @@ -314,34 +322,45 @@ out: return; } +static void cg1_mem_stats(struct lxc_container *c, struct mem_stats *mem) +{ + mem->used = stat_get_int(c, "memory.usage_in_bytes"); + mem->limit = stat_get_int(c, "memory.limit_in_bytes"); + mem->swap_used = stat_get_int(c, "memory.memsw.usage_in_bytes"); + mem->swap_limit = stat_get_int(c, "memory.memsw.limit_in_bytes"); + mem->kmem_used = stat_get_int(c, "memory.kmem.usage_in_bytes"); + mem->kmem_limit = stat_get_int(c, "memory.kmem.limit_in_bytes"); +} + +static void cg1_cpu_stats(struct lxc_container *c, struct cpu_stats *cpu) +{ + cpu->use_nanos = stat_get_int(c, "cpuacct.usage"); + cpu->use_user = stat_match_get_int(c, "cpuacct.stat", "user", 1); + cpu->use_sys = stat_match_get_int(c, "cpuacct.stat", "system", 1); +} + static void stats_get(struct lxc_container *c, struct container_stats *ct, struct stats *total) { ct->c = c; - ct->stats->mem_used = stat_get_int(c, "memory.usage_in_bytes"); - ct->stats->mem_limit = stat_get_int(c, "memory.limit_in_bytes"); - ct->stats->memsw_used = stat_get_int(c, "memory.memsw.usage_in_bytes"); - ct->stats->memsw_limit = stat_get_int(c, "memory.memsw.limit_in_bytes"); - ct->stats->kmem_used = stat_get_int(c, "memory.kmem.usage_in_bytes"); - ct->stats->kmem_limit = stat_get_int(c, "memory.kmem.limit_in_bytes"); - ct->stats->cpu_use_nanos = stat_get_int(c, "cpuacct.usage"); - ct->stats->cpu_use_user = stat_match_get_int(c, "cpuacct.stat", "user", 1); - ct->stats->cpu_use_sys = stat_match_get_int(c, "cpuacct.stat", "system", 1); - + cg1_mem_stats(c, &ct->stats->mem); + cg1_cpu_stats(c, &ct->stats->cpu); stat_get_blk_stats(c, "blkio.throttle.io_service_bytes", &ct->stats->io_service_bytes); stat_get_blk_stats(c, "blkio.throttle.io_serviced", &ct->stats->io_serviced); if (total) { - total->mem_used = total->mem_used + ct->stats->mem_used; - total->mem_limit = total->mem_limit + ct->stats->mem_limit; - total->memsw_used = total->memsw_used + ct->stats->memsw_used; - total->memsw_limit = total->memsw_limit + ct->stats->memsw_limit; - total->kmem_used = total->kmem_used + ct->stats->kmem_used; - total->kmem_limit = total->kmem_limit + ct->stats->kmem_limit; - total->cpu_use_nanos = total->cpu_use_nanos + ct->stats->cpu_use_nanos; - total->cpu_use_user = total->cpu_use_user + ct->stats->cpu_use_user; - total->cpu_use_sys = total->cpu_use_sys + ct->stats->cpu_use_sys; + total->mem.used += ct->stats->mem.used; + total->mem.limit += ct->stats->mem.limit; + total->mem.swap_used += ct->stats->mem.swap_used; + total->mem.swap_limit += ct->stats->mem.swap_limit; + total->mem.kmem_used += ct->stats->mem.kmem_used; + total->mem.kmem_limit += ct->stats->mem.kmem_limit; + + total->cpu.use_nanos += ct->stats->cpu.use_nanos; + total->cpu.use_user += ct->stats->cpu.use_user; + total->cpu.use_sys += ct->stats->cpu.use_sys; + total->io_service_bytes.total += ct->stats->io_service_bytes.total; - total->io_service_bytes.read += ct->stats->io_service_bytes.read; + total->io_service_bytes.read += ct->stats->io_service_bytes.read; total->io_service_bytes.write += ct->stats->io_service_bytes.write; } } @@ -351,19 +370,19 @@ static void stats_print_header(struct stats *stats) printf(TERMRVRS TERMBOLD); printf("%-18s %12s %12s %12s %36s %10s", "Container", "CPU", "CPU", "CPU", "BlkIO", "Mem"); - if (stats->memsw_used > 0) + if (stats->mem.swap_used > 0) printf(" %10s", "MemSw"); - if (stats->kmem_used > 0) + if (stats->mem.kmem_used > 0) printf(" %10s", "KMem"); printf("\n"); printf("%-18s %12s %12s %12s %36s %10s", "Name", "Used", "Sys", "User", "Total(Read/Write)", "Used"); - if (stats->memsw_used > 0) + if (stats->mem.swap_used > 0) printf(" %10s", "Used"); - if (stats->kmem_used > 0) + if (stats->mem.kmem_used > 0) printf(" %10s", "Used"); printf("\n"); @@ -388,7 +407,7 @@ static void stats_print(const char *name, const struct stats *stats, size_humanize(stats->io_service_bytes.total, iosb_total_str, sizeof(iosb_total_str)); size_humanize(stats->io_service_bytes.read, iosb_read_str, sizeof(iosb_read_str)); size_humanize(stats->io_service_bytes.write, iosb_write_str, sizeof(iosb_write_str)); - size_humanize(stats->mem_used, mem_used_str, sizeof(mem_used_str)); + size_humanize(stats->mem.used, mem_used_str, sizeof(mem_used_str)); ret = snprintf(iosb_str, sizeof(iosb_str), "%s(%s/%s)", iosb_total_str, iosb_read_str, iosb_write_str); if (ret < 0 || (size_t)ret >= sizeof(iosb_str)) @@ -396,18 +415,18 @@ static void stats_print(const char *name, const struct stats *stats, printf("%-18.18s %12.2f %12.2f %12.2f %36s %10s", name, - (float)stats->cpu_use_nanos / 1000000000, - (float)stats->cpu_use_sys / USER_HZ, - (float)stats->cpu_use_user / USER_HZ, + (float)stats->cpu.use_nanos / 1000000000, + (float)stats->cpu.use_sys / USER_HZ, + (float)stats->cpu.use_user / USER_HZ, iosb_str, mem_used_str); - if (total->memsw_used > 0) { - size_humanize(stats->memsw_used, memsw_used_str, sizeof(memsw_used_str)); + if (total->mem.swap_used > 0) { + size_humanize(stats->mem.swap_used, memsw_used_str, sizeof(memsw_used_str)); printf(" %10s", memsw_used_str); } - if (total->kmem_used > 0) { - size_humanize(stats->kmem_used, kmem_used_str, sizeof(kmem_used_str)); + if (total->mem.kmem_used > 0) { + size_humanize(stats->mem.kmem_used, kmem_used_str, sizeof(kmem_used_str)); printf(" %10s", kmem_used_str); } } else { @@ -415,11 +434,11 @@ static void stats_print(const char *name, const struct stats *stats, time_ms = (unsigned long long) (time_val.tv_sec) * 1000 + (unsigned long long) (time_val.tv_usec) / 1000; printf("%" PRIu64 ",%s,%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64, - (uint64_t)time_ms, name, (uint64_t)stats->cpu_use_nanos, - (uint64_t)stats->cpu_use_sys, - (uint64_t)stats->cpu_use_user, (uint64_t)stats->io_service_bytes.total, - (uint64_t)stats->io_serviced.total, (uint64_t)stats->mem_used, - (uint64_t)stats->memsw_used, (uint64_t)stats->kmem_used); + (uint64_t)time_ms, name, (uint64_t)stats->cpu.use_nanos, + (uint64_t)stats->cpu.use_sys, + (uint64_t)stats->cpu.use_user, (uint64_t)stats->io_service_bytes.total, + (uint64_t)stats->io_serviced.total, (uint64_t)stats->mem.used, + (uint64_t)stats->mem.swap_used, (uint64_t)stats->mem.kmem_used); } } @@ -441,9 +460,9 @@ static int cmp_cpuuse(const void *sct1, const void *sct2) const struct container_stats *ct2 = sct2; if (sort_reverse) - return ct2->stats->cpu_use_nanos < ct1->stats->cpu_use_nanos; + return ct2->stats->cpu.use_nanos < ct1->stats->cpu.use_nanos; - return ct1->stats->cpu_use_nanos < ct2->stats->cpu_use_nanos; + return ct1->stats->cpu.use_nanos < ct2->stats->cpu.use_nanos; } static int cmp_blkio(const void *sct1, const void *sct2) @@ -463,9 +482,9 @@ static int cmp_memory(const void *sct1, const void *sct2) const struct container_stats *ct2 = sct2; if (sort_reverse) - return ct2->stats->mem_used < ct1->stats->mem_used; + return ct2->stats->mem.used < ct1->stats->mem.used; - return ct1->stats->mem_used < ct2->stats->mem_used; + return ct1->stats->mem.used < ct2->stats->mem.used; } static int cmp_memorysw(const void *sct1, const void *sct2) @@ -474,9 +493,9 @@ static int cmp_memorysw(const void *sct1, const void *sct2) const struct container_stats *ct2 = sct2; if (sort_reverse) - return ct2->stats->memsw_used < ct1->stats->memsw_used; + return ct2->stats->mem.swap_used < ct1->stats->mem.swap_used; - return ct1->stats->memsw_used < ct2->stats->memsw_used; + return ct1->stats->mem.swap_used < ct2->stats->mem.swap_used; } static int cmp_kmemory(const void *sct1, const void *sct2) @@ -485,9 +504,9 @@ static int cmp_kmemory(const void *sct1, const void *sct2) const struct container_stats *ct2 = sct2; if (sort_reverse) - return ct2->stats->kmem_used < ct1->stats->kmem_used; + return ct2->stats->mem.kmem_used < ct1->stats->mem.kmem_used; - return ct1->stats->kmem_used < ct2->stats->kmem_used; + return ct1->stats->mem.kmem_used < ct2->stats->mem.kmem_used; } static void ct_sort(int active) -- 2.45.2 From ec11c2dad1ccf5fd6dd9a57e2812c4551f8a710f Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 24 Jul 2024 15:47:55 +0200 Subject: [PATCH 2/7] tools: lxc-top: get memory stats from cgroups2 Signed-off-by: Natanael Copa --- src/lxc/tools/lxc_top.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index bcc695b3e..29d81563f 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -212,7 +212,6 @@ static uint64_t stat_get_int(struct lxc_container *c, const char *item) len = c->get_cgroup_item(c, item, buf, sizeof(buf)); if (len <= 0) { - fprintf(stderr, "Unable to read cgroup item %s\n", item); return 0; } @@ -322,7 +321,7 @@ out: return; } -static void cg1_mem_stats(struct lxc_container *c, struct mem_stats *mem) +static int cg1_mem_stats(struct lxc_container *c, struct mem_stats *mem) { mem->used = stat_get_int(c, "memory.usage_in_bytes"); mem->limit = stat_get_int(c, "memory.limit_in_bytes"); @@ -330,6 +329,20 @@ static void cg1_mem_stats(struct lxc_container *c, struct mem_stats *mem) mem->swap_limit = stat_get_int(c, "memory.memsw.limit_in_bytes"); mem->kmem_used = stat_get_int(c, "memory.kmem.usage_in_bytes"); mem->kmem_limit = stat_get_int(c, "memory.kmem.limit_in_bytes"); + return mem->used > 0 ? 0 : -1; +} + +static int cg2_mem_stats(struct lxc_container *c, struct mem_stats *mem) +{ + mem->used = stat_get_int(c, "memory.current"); + mem->limit = stat_get_int(c, "memory.max"); + mem->swap_used = stat_get_int(c, "memory.swap.current"); + mem->swap_limit = stat_get_int(c, "memory.swap.max"); + /* TODO: find the kernel usage */ + mem->kmem_used = 0; + /* does not exist in cgroup v2 */ + mem->kmem_limit = 0; + return mem->used > 0 ? 0 : -1; } static void cg1_cpu_stats(struct lxc_container *c, struct cpu_stats *cpu) @@ -342,7 +355,11 @@ static void cg1_cpu_stats(struct lxc_container *c, struct cpu_stats *cpu) static void stats_get(struct lxc_container *c, struct container_stats *ct, struct stats *total) { ct->c = c; - cg1_mem_stats(c, &ct->stats->mem); + if (cg1_mem_stats(c, &ct->stats->mem) < 0) { + if (cg2_mem_stats(c, &ct->stats->mem) < 0) { + fprintf(stderr, "Unable to read memory stats\n"); + } + } cg1_cpu_stats(c, &ct->stats->cpu); stat_get_blk_stats(c, "blkio.throttle.io_service_bytes", &ct->stats->io_service_bytes); stat_get_blk_stats(c, "blkio.throttle.io_serviced", &ct->stats->io_serviced); -- 2.45.2 From df219e84ca11294ba29ff9e85d09f4190942b30c Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 24 Jul 2024 16:32:30 +0200 Subject: [PATCH 3/7] lxc-top: CPU stats for cgroups2 Recalculate the usec to nanoseconds and USER_HZ Signed-off-by: Natanael Copa --- src/lxc/tools/lxc_top.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index 29d81563f..3a6c49e82 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -230,7 +230,6 @@ static uint64_t stat_match_get_int(struct lxc_container *c, const char *item, len = c->get_cgroup_item(c, item, buf, sizeof(buf)); if (len <= 0) { - fprintf(stderr, "Unable to read cgroup item %s\n", item); goto out; } @@ -345,11 +344,22 @@ static int cg2_mem_stats(struct lxc_container *c, struct mem_stats *mem) return mem->used > 0 ? 0 : -1; } -static void cg1_cpu_stats(struct lxc_container *c, struct cpu_stats *cpu) +static int cg1_cpu_stats(struct lxc_container *c, struct cpu_stats *cpu) { cpu->use_nanos = stat_get_int(c, "cpuacct.usage"); cpu->use_user = stat_match_get_int(c, "cpuacct.stat", "user", 1); cpu->use_sys = stat_match_get_int(c, "cpuacct.stat", "system", 1); + return cpu->use_nanos > 0 ? 0 : -1; +} + +static int cg2_cpu_stats(struct lxc_container *c, struct cpu_stats *cpu) +{ + /* convert microseconds to nanoseconds */ + cpu->use_nanos = stat_match_get_int(c, "cpu.stat", "usage_usec", 1) * 1000; + + cpu->use_user = stat_match_get_int(c, "cpu.stat", "user_usec", 1) * USER_HZ / 1000000; + cpu->use_sys = stat_match_get_int(c, "cpu.stat", "system_usec", 1) * USER_HZ / 1000000; + return cpu->use_nanos > 0 ? 0 : -1; } static void stats_get(struct lxc_container *c, struct container_stats *ct, struct stats *total) @@ -360,7 +370,12 @@ static void stats_get(struct lxc_container *c, struct container_stats *ct, struc fprintf(stderr, "Unable to read memory stats\n"); } } - cg1_cpu_stats(c, &ct->stats->cpu); + if (cg1_cpu_stats(c, &ct->stats->cpu) < 0) { + if (cg2_cpu_stats(c, &ct->stats->cpu) < 0) { + fprintf(stderr, "Unable to read CPU stats\n"); + } + } + stat_get_blk_stats(c, "blkio.throttle.io_service_bytes", &ct->stats->io_service_bytes); stat_get_blk_stats(c, "blkio.throttle.io_serviced", &ct->stats->io_serviced); -- 2.45.2 From 094f05141db5968f8e3a855e4230579b12721a65 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 24 Jul 2024 16:54:00 +0200 Subject: [PATCH 4/7] tools: lxc-top: get the user HZ at runtime The USER_HZ depends on the kernel configuration. Get it run-time instead of assume it is 100 HZ. Signed-off-by: Natanael Copa --- src/lxc/tools/lxc_top.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index 3a6c49e82..deea1b41d 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -22,7 +22,6 @@ #include "mainloop.h" #include "utils.h" -#define USER_HZ 100 #define ESC "\033" #define TERMCLEAR ESC "[H" ESC "[J" #define TERMNORM ESC "[0m" @@ -70,6 +69,7 @@ static int sort_reverse = 0; static struct termios oldtios; static struct container_stats *container_stats = NULL; static int ct_alloc_cnt = 0; +static long user_hz = 0; static int my_parser(struct lxc_arguments *args, int c, char *arg) { @@ -357,8 +357,8 @@ static int cg2_cpu_stats(struct lxc_container *c, struct cpu_stats *cpu) /* convert microseconds to nanoseconds */ cpu->use_nanos = stat_match_get_int(c, "cpu.stat", "usage_usec", 1) * 1000; - cpu->use_user = stat_match_get_int(c, "cpu.stat", "user_usec", 1) * USER_HZ / 1000000; - cpu->use_sys = stat_match_get_int(c, "cpu.stat", "system_usec", 1) * USER_HZ / 1000000; + cpu->use_user = stat_match_get_int(c, "cpu.stat", "user_usec", 1) * user_hz / 1000000; + cpu->use_sys = stat_match_get_int(c, "cpu.stat", "system_usec", 1) * user_hz / 1000000; return cpu->use_nanos > 0 ? 0 : -1; } @@ -448,8 +448,8 @@ static void stats_print(const char *name, const struct stats *stats, printf("%-18.18s %12.2f %12.2f %12.2f %36s %10s", name, (float)stats->cpu.use_nanos / 1000000000, - (float)stats->cpu.use_sys / USER_HZ, - (float)stats->cpu.use_user / USER_HZ, + (float)stats->cpu.use_sys / user_hz, + (float)stats->cpu.use_user / user_hz, iosb_str, mem_used_str); @@ -640,6 +640,11 @@ int lxc_top_main(int argc, char *argv[]) signal(SIGINT, sig_handler); signal(SIGQUIT, sig_handler); + user_hz = sysconf(_SC_CLK_TCK); + if (user_hz == 0) { + user_hz = 100; + } + if (lxc_mainloop_open(&descr)) { fprintf(stderr, "Failed to create mainloop\n"); goto out; -- 2.45.2 From ebf0bbb3585330bf80bdd01aa7597672cca07aba Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 24 Jul 2024 17:29:10 +0200 Subject: [PATCH 5/7] tools: lxc-top: add cgroups2 IO stats Signed-off-by: Natanael Copa --- src/lxc/tools/lxc_top.c | 60 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index deea1b41d..15cf75a9a 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -281,21 +281,21 @@ examples: 8:0 Total 149327872 Total 149327872 */ -static void stat_get_blk_stats(struct lxc_container *c, const char *item, +static int cg1_get_blk_stats(struct lxc_container *c, const char *item, struct blkio_stats *stats) { char buf[4096]; int i, len; char **lines, **cols; + int ret = -1; len = c->get_cgroup_item(c, item, buf, sizeof(buf)); if (len <= 0 || (size_t)len >= sizeof(buf)) { - fprintf(stderr, "Unable to read cgroup item %s\n", item); - return; + return ret; } lines = lxc_string_split_and_trim(buf, '\n'); if (!lines) - return; + return ret; memset(stats, 0, sizeof(struct blkio_stats)); @@ -314,10 +314,50 @@ static void stat_get_blk_stats(struct lxc_container *c, const char *item, lxc_free_array((void **)cols, free); } + ret = 0; +out: + lxc_free_array((void **)lines, free); + return ret; +} + +static int cg2_get_blk_stats(struct lxc_container *c, const char *item, + struct blkio_stats *stats) { + char buf[4096]; + int i, j, len; + char **lines, **cols; + int ret = -1; + len = c->get_cgroup_item(c, item, buf, sizeof(buf)); + if (len <= 0 || (size_t)len >= sizeof(buf)) { + return ret; + } + + lines = lxc_string_split_and_trim(buf, '\n'); + if (!lines) + return ret; + + memset(stats, 0, sizeof(struct blkio_stats)); + + for (i = 0; lines[i]; i++) { + cols = lxc_string_split_and_trim(lines[i], ' '); + if (!cols) + goto out; + + for (j = 0; cols[j]; j++) { + if (strncmp(cols[j], "rbytes=", 7) == 0) { + stats->read += strtoull(&cols[j][7], NULL, 0); + } else if (strncmp(cols[j], "wbytes=", 7) == 0) { + stats->write += strtoull(&cols[j][7], NULL, 0); + } + } + + lxc_free_array((void **)cols, free); + } + stats->total = stats->read + stats->write; + ret = 0; out: lxc_free_array((void **)lines, free); - return; + return ret; } static int cg1_mem_stats(struct lxc_container *c, struct mem_stats *mem) @@ -376,8 +416,14 @@ static void stats_get(struct lxc_container *c, struct container_stats *ct, struc } } - stat_get_blk_stats(c, "blkio.throttle.io_service_bytes", &ct->stats->io_service_bytes); - stat_get_blk_stats(c, "blkio.throttle.io_serviced", &ct->stats->io_serviced); + if (cg1_get_blk_stats(c, "blkio.throttle.io_service_bytes", &ct->stats->io_service_bytes) < 0) { + if (cg2_get_blk_stats(c, "io.stat", &ct->stats->io_service_bytes) < 0) { + fprintf(stderr, "Unable to read IO stats\n"); + } + } else { + /* only with cgroups v1 */ + cg1_get_blk_stats(c, "blkio.throttle.io_serviced", &ct->stats->io_serviced); + } if (total) { total->mem.used += ct->stats->mem.used; -- 2.45.2 From 54e8ff395303f0d121cdb603a0ea5c01dd134dc3 Mon Sep 17 00:00:00 2001 From: Devon Schwartz Date: Wed, 24 Jul 2024 22:17:32 -0500 Subject: [PATCH 6/7] lxc-top: added kernel memory usage for cgroup2 --- src/lxc/tools/lxc_top.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index 15cf75a9a..6cb38bb90 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -373,14 +373,13 @@ static int cg1_mem_stats(struct lxc_container *c, struct mem_stats *mem) static int cg2_mem_stats(struct lxc_container *c, struct mem_stats *mem) { - mem->used = stat_get_int(c, "memory.current"); - mem->limit = stat_get_int(c, "memory.max"); - mem->swap_used = stat_get_int(c, "memory.swap.current"); - mem->swap_limit = stat_get_int(c, "memory.swap.max"); - /* TODO: find the kernel usage */ - mem->kmem_used = 0; + mem->used = stat_get_int(c, "memory.current"); + mem->limit = stat_get_int(c, "memory.max"); + mem->swap_used = stat_get_int(c, "memory.swap.current"); + mem->swap_limit = stat_get_int(c, "memory.swap.max"); + mem->kmem_used = stat_match_get_int(c, "memory.stat", "kernel", 1); /* does not exist in cgroup v2 */ - mem->kmem_limit = 0; + // mem->kmem_limit = 0; return mem->used > 0 ? 0 : -1; } -- 2.45.2 From 9a7c15337202a00ae7d0a87906b3529f3ab9b84b Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 25 Jul 2024 13:52:27 +0200 Subject: [PATCH 7/7] tools: lxc-top: fix print in batch mode We should not care about the number of rows when printing stats in batch mode. --- src/lxc/tools/lxc_top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index 6cb38bb90..7498331ee 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -732,7 +732,7 @@ int lxc_top_main(int argc, char *argv[]) stats_print_header(&total); } - for (i = 0; i < active_cnt && i < ct_print_cnt; i++) { + for (i = 0; i < active_cnt && (i < ct_print_cnt || batch); i++) { stats_print(container_stats[i].c->name, container_stats[i].stats, &total); printf("\n"); } -- 2.45.2