Skip to content

Commit

Permalink
Merge pull request #508 from Blub/2021-12-09/cgv2-swap-meminfo
Browse files Browse the repository at this point in the history
make meminfo and swaps cgroupv2 aware
  • Loading branch information
Christian Brauner authored Dec 9, 2021
2 parents 0cbe135 + 50f7fae commit 80613fb
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 43 deletions.
10 changes: 10 additions & 0 deletions src/bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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__);

Expand Down Expand Up @@ -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]);
Expand Down
1 change: 1 addition & 0 deletions src/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
89 changes: 46 additions & 43 deletions src/proc_fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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 = {};
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 80613fb

Please sign in to comment.