mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-04-20 00:16:38 +02:00
630 lines
22 KiB
Diff
630 lines
22 KiB
Diff
From 40857b9de3714b3314f5c22e924d5993c458acbe Mon Sep 17 00:00:00 2001
|
|
From: Natanael Copa <ncopa@alpinelinux.org>
|
|
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 <ncopa@alpinelinux.org>
|
|
---
|
|
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 <ncopa@alpinelinux.org>
|
|
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 <ncopa@alpinelinux.org>
|
|
---
|
|
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 <ncopa@alpinelinux.org>
|
|
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 <ncopa@alpinelinux.org>
|
|
---
|
|
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 <ncopa@alpinelinux.org>
|
|
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 <ncopa@alpinelinux.org>
|
|
---
|
|
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 <ncopa@alpinelinux.org>
|
|
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 <ncopa@alpinelinux.org>
|
|
---
|
|
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 <devon.s.schwartz@gmail.com>
|
|
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 <ncopa@alpinelinux.org>
|
|
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
|
|
|