From 50f7faeec2029f141836d91a6403ef9273b1a0cd Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Thu, 9 Dec 2021 11:37:04 +0100 Subject: [PATCH] make meminfo and swaps cgroupv2 aware and deduplicate the corresponding code Signed-off-by: Wolfgang Bumiller --- src/bindings.c | 10 ++++++ src/bindings.h | 1 + src/proc_fuse.c | 89 +++++++++++++++++++++++++------------------------ 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index eb62ddbd..e417a13a 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -44,6 +44,7 @@ static bool can_use_pidfd; static bool can_use_swap; static bool can_use_sys_cpu; static bool has_versioned_opts; +static bool memory_is_cgroupv2; static volatile sig_atomic_t reload_successful; @@ -67,6 +68,11 @@ bool liblxcfs_has_versioned_opts(void) return has_versioned_opts; } +bool liblxcfs_memory_is_cgroupv2(void) +{ + return memory_is_cgroupv2; +} + /* Define pivot_root() if missing from the C library */ #ifndef HAVE_PIVOT_ROOT static int pivot_root(const char *new_root, const char *put_old) @@ -837,6 +843,7 @@ static void __attribute__((constructor)) lxcfs_init(void) pidfd = -EBADF; int i = 0; pid_t pid; + struct hierarchy *hierarchy; lxcfs_info("Running constructor %s to reload liblxcfs", __func__); @@ -894,6 +901,9 @@ static void __attribute__((constructor)) lxcfs_init(void) else lxcfs_info("Kernel does not support swap accounting"); + hierarchy = cgroup_ops->get_hierarchy(cgroup_ops, "memory"); + memory_is_cgroupv2 = hierarchy && is_unified_hierarchy(hierarchy); + lxcfs_info("api_extensions:"); for (size_t nr = 0; nr < nr_api_extensions; nr++) lxcfs_info("- %s", api_extensions[nr]); diff --git a/src/bindings.h b/src/bindings.h index a278aa7a..e35423ac 100644 --- a/src/bindings.h +++ b/src/bindings.h @@ -104,6 +104,7 @@ extern void prune_init_slice(char *cg); extern bool supports_pidfd(void); extern bool liblxcfs_functional(void); extern bool liblxcfs_can_use_swap(void); +extern bool liblxcfs_memory_is_cgroupv2(void); extern bool liblxcfs_can_use_sys_cpu(void); extern bool liblxcfs_has_versioned_opts(void); diff --git a/src/proc_fuse.c b/src/proc_fuse.c index 4ac5d44b..c9103771 100644 --- a/src/proc_fuse.c +++ b/src/proc_fuse.c @@ -303,6 +303,43 @@ static inline bool startswith(const char *line, const char *pref) return strncmp(line, pref, strlen(pref)) == 0; } +static void get_swap_info(const char *cgroup, uint64_t memlimit, + uint64_t memusage, uint64_t *swtotal, + uint64_t *swusage, uint64_t *memswpriority) +{ + __do_free char *memswusage_str = NULL, *memswpriority_str = NULL; + size_t memswlimit = 0, memswusage = 0; + int ret; + + *swtotal = *swusage = 0; + *memswpriority = 1; + + memswlimit = get_min_memlimit(cgroup, true); + if (memswlimit > 0) { + ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str); + if (ret < 0 || safe_uint64(memswusage_str, &memswusage, 10) != 0) + return; + + if (liblxcfs_memory_is_cgroupv2()) { + *swtotal = memswlimit / 1024; + *swusage = memswusage / 1024; + } else { + if (memlimit > memswlimit) + *swtotal = 0; + else + *swtotal = (memswlimit - memlimit) / 1024; + if (memusage > memswusage || swtotal == 0) + *swusage = 0; + else + *swusage = (memswusage - memusage) / 1024; + } + + ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str); + if (ret >= 0) + safe_uint64(memswpriority_str, memswpriority, 10); + } +} + static int proc_swaps_read(char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { @@ -311,7 +348,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, struct fuse_context *fc = fuse_get_context(); bool wants_swap = lxcfs_has_opt(fuse_get_context()->private_data, LXCFS_SWAP_ON); struct file_info *d = INTTYPE_TO_PTR(fi->fh); - uint64_t memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0, + uint64_t memlimit = 0, memusage = 0, swtotal = 0, swusage = 0, memswpriority = 1, hostswtotal = 0, hostswfree = 0; ssize_t total_len = 0; @@ -357,26 +394,8 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, if (safe_uint64(memusage_str, &memusage, 10) < 0) lxcfs_error("Failed to convert memusage %s", memusage_str); - if (wants_swap) { - memswlimit = get_min_memlimit(cgroup, true); - if (memswlimit > 0) { - ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str); - if (ret >= 0 && safe_uint64(memswusage_str, &memswusage, 10) == 0) { - if (memlimit > memswlimit) - swtotal = 0; - else - swtotal = (memswlimit - memlimit) / 1024; - if (memusage > memswusage || swtotal == 0) - swusage = 0; - else - swusage = (memswusage - memusage) / 1024; - } - - ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str); - if (ret >= 0) - safe_uint64(memswpriority_str, &memswpriority, 10); - } - } + if (wants_swap) + get_swap_info(cgroup, memlimit, memusage, &swtotal, &swusage, &memswpriority); total_len = snprintf(d->buf, d->size, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); @@ -1145,7 +1164,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, struct fuse_context *fc = fuse_get_context(); bool wants_swap = lxcfs_has_opt(fuse_get_context()->private_data, LXCFS_SWAP_ON); struct file_info *d = INTTYPE_TO_PTR(fi->fh); - uint64_t memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, + uint64_t memlimit = 0, memusage = 0, hosttotal = 0, swfree = 0, swusage = 0, swtotal = 0, memswpriority = 1; struct memory_stat mstat = {}; @@ -1197,26 +1216,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, * Following values are allowed to fail, because swapaccount might be * turned off for current kernel. */ - if (wants_swap) { - memswlimit = get_min_memlimit(cgroup, true); - if (memswlimit > 0) { - ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str); - if (ret >= 0 && safe_uint64(memswusage_str, &memswusage, 10) == 0) { - if (memlimit > memswlimit) - swtotal = 0; - else - swtotal = (memswlimit - memlimit) / 1024; - if (memusage > memswusage || swtotal == 0) - swusage = 0; - else - swusage = (memswusage - memusage) / 1024; - } - } - - ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str); - if (ret >= 0) - safe_uint64(memswpriority_str, &memswpriority, 10); - } + if (wants_swap) + get_swap_info(cgroup, memlimit, memusage, &swtotal, &swusage, &memswpriority); f = fopen_cached("/proc/meminfo", "re", &fopen_cache); if (!f) @@ -1255,7 +1256,9 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, This is because the kernel can swap as much as it wants and not only up to swtotal. */ - swtotal = memlimit + swtotal; + if (!liblxcfs_memory_is_cgroupv2()) + swtotal += memlimit; + if (hostswtotal < swtotal) { swtotal = hostswtotal; }