[lxc-devel] [lxcfs/master] bindings: port memory to new cgroup getters and support cgroup2
brauner on Github
lxc-bot at linuxcontainers.org
Fri Feb 21 14:40:09 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 367 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200221/4e522768/attachment.bin>
-------------- next part --------------
From cfb72d52826919885019a3170cc28b4da3641d13 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 21 Feb 2020 14:05:56 +0100
Subject: [PATCH 1/2] bindings: rework proc meminfo helpers
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
bindings.c | 114 ++++++++++++++++++++++++++++-------------------------
1 file changed, 61 insertions(+), 53 deletions(-)
diff --git a/bindings.c b/bindings.c
index 9d8cc33..31c4ccc 100644
--- a/bindings.c
+++ b/bindings.c
@@ -3285,22 +3285,22 @@ int read_file_fuse(const char *path, char *buf, size_t size, struct file_info *d
static unsigned long get_memlimit(const char *cgroup, const char *file)
{
- char *memlimit_str = NULL;
+ __do_free char *memlimit_str = NULL;
unsigned long memlimit = -1;
if (cgroup_ops->get(cgroup_ops, "memory", cgroup, file, &memlimit_str))
memlimit = strtoul(memlimit_str, NULL, 10);
- free(memlimit_str);
-
return memlimit;
}
static unsigned long get_min_memlimit(const char *cgroup, const char *file)
{
- char *copy = strdupa(cgroup);
- unsigned long memlimit = 0, retlimit;
+ __do_free char *copy = NULL;
+ unsigned long memlimit = 0;
+ unsigned long retlimit;
+ copy = strdupa(cgroup);
retlimit = get_memlimit(copy, file);
while (strcmp(copy, "/") != 0) {
@@ -3314,57 +3314,70 @@ static unsigned long get_min_memlimit(const char *cgroup, const char *file)
}
static int proc_meminfo_read(char *buf, size_t size, off_t offset,
- struct fuse_file_info *fi)
+ struct fuse_file_info *fi)
{
+ __do_free char *current_cgroup = NULL, *line = NULL,
+ *memusage_str = NULL, *memstat_str = NULL,
+ *memswlimit_str = NULL, *memswusage_str = NULL;
+ __do_fclose FILE *f = NULL;
struct fuse_context *fc = fuse_get_context();
struct lxcfs_opts *opts = (struct lxcfs_opts *) fuse_get_context()->private_data;
struct file_info *d = (struct file_info *)fi->fh;
- char *cg;
- char *memusage_str = NULL, *memstat_str = NULL,
- *memswlimit_str = NULL, *memswusage_str = NULL;
- unsigned long memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0,
- cached = 0, hosttotal = 0, active_anon = 0, inactive_anon = 0,
- active_file = 0, inactive_file = 0, unevictable = 0, shmem = 0,
- hostswtotal = 0;
- char *line = NULL;
+ unsigned long memlimit = 0, memusage = 0, memswlimit = 0,
+ memswusage = 0, cached = 0, hosttotal = 0, active_anon = 0,
+ inactive_anon = 0, active_file = 0, inactive_file = 0,
+ unevictable = 0, shmem = 0, hostswtotal = 0;
size_t linelen = 0, total_len = 0, rv = 0;
char *cache = d->buf;
size_t cache_size = d->buflen;
- FILE *f = NULL;
- if (offset){
+ if (offset) {
+ int left;
+
if (offset > d->size)
return -EINVAL;
+
if (!d->cached)
return 0;
- int left = d->size - offset;
- total_len = left > size ? size: left;
+
+ left = d->size - offset;
+ total_len = left > size ? size : left;
memcpy(buf, cache + offset, total_len);
+
return total_len;
}
pid_t initpid = lookup_initpid_in_store(fc->pid);
if (initpid <= 1 || is_shared_pidns(initpid))
initpid = fc->pid;
- cg = get_pid_cgroup(initpid, "memory");
- if (!cg)
+
+ current_cgroup = get_pid_cgroup(initpid, "memory");
+ if (!current_cgroup)
return read_file_fuse("/proc/meminfo", buf, size, d);
- prune_init_slice(cg);
- memlimit = get_min_memlimit(cg, "memory.limit_in_bytes");
- if (!cgroup_ops->get(cgroup_ops, "memory", cg, "memory.usage_in_bytes", &memusage_str))
- goto err;
- if (!cgroup_ops->get(cgroup_ops, "memory", cg, "memory.stat", &memstat_str))
- goto err;
+ prune_init_slice(current_cgroup);
- // Following values are allowed to fail, because swapaccount might be turned
- // off for current kernel
- if(cgroup_ops->get(cgroup_ops, "memory", cg, "memory.memsw.limit_in_bytes", &memswlimit_str) &&
- cgroup_ops->get(cgroup_ops, "memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str))
- {
- memswlimit = get_min_memlimit(cg, "memory.memsw.limit_in_bytes");
- memswusage = strtoul(memswusage_str, NULL, 10);
+ memlimit = get_min_memlimit(current_cgroup, "memory.limit_in_bytes");
+
+ if (!cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
+ "memory.usage_in_bytes", &memusage_str))
+ return 0;
+ if (!cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
+ "memory.stat", &memstat_str))
+ return 0;
+
+ /*
+ * Following values are allowed to fail, because swapaccount might be
+ * turned off for current kernel.
+ */
+ if (cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
+ "memory.memsw.limit_in_bytes", &memswlimit_str) &&
+ cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
+ "memory.memsw.usage_in_bytes", &memswusage_str)) {
+ memswlimit = get_min_memlimit(current_cgroup,
+ "memory.memsw.limit_in_bytes");
+ memswusage = strtoul(memswusage_str, NULL, 10);
memswlimit = memswlimit / 1024;
memswusage = memswusage / 1024;
}
@@ -3373,13 +3386,12 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
memlimit /= 1024;
memusage /= 1024;
- parse_memstat(memstat_str, &cached, &active_anon,
- &inactive_anon, &active_file, &inactive_file,
- &unevictable, &shmem);
+ parse_memstat(memstat_str, &cached, &active_anon, &inactive_anon,
+ &active_file, &inactive_file, &unevictable, &shmem);
f = fopen("/proc/meminfo", "r");
if (!f)
- goto err;
+ return 0;
while (getline(&line, &linelen, f) != -1) {
ssize_t l;
@@ -3398,7 +3410,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
} else if (startswith(line, "MemAvailable:")) {
snprintf(lbuf, 100, "MemAvailable: %8lu kB\n", memlimit - memusage + cached);
printme = lbuf;
- } else if (startswith(line, "SwapTotal:") && memswlimit > 0 && opts && opts->swap_off == false) {
+ } else if (startswith(line, "SwapTotal:") && memswlimit > 0 &&
+ opts && opts->swap_off == false) {
sscanf(line+sizeof("SwapTotal:")-1, "%lu", &hostswtotal);
if (hostswtotal < memswlimit)
memswlimit = hostswtotal;
@@ -3407,10 +3420,15 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
} else if (startswith(line, "SwapTotal:") && opts && opts->swap_off == true) {
snprintf(lbuf, 100, "SwapTotal: %8lu kB\n", 0UL);
printme = lbuf;
- } else if (startswith(line, "SwapFree:") && memswlimit > 0 && memswusage > 0 && opts && opts->swap_off == false) {
+ } else if (startswith(line, "SwapFree:") && memswlimit > 0 &&
+ memswusage > 0 && opts && opts->swap_off == false) {
unsigned long swaptotal = memswlimit,
- swapusage = memusage > memswusage ? 0 : memswusage - memusage,
- swapfree = swapusage < swaptotal ? swaptotal - swapusage : 0;
+ swapusage = memusage > memswusage
+ ? 0
+ : memswusage - memusage,
+ swapfree = swapusage < swaptotal
+ ? swaptotal - swapusage
+ : 0;
snprintf(lbuf, 100, "SwapFree: %8lu kB\n", swapfree);
printme = lbuf;
} else if (startswith(line, "SwapFree:") && opts && opts->swap_off == true) {
@@ -3472,14 +3490,12 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
l = snprintf(cache, cache_size, "%s", printme);
if (l < 0) {
perror("Error writing to cache");
- rv = 0;
- goto err;
+ return 0;
}
if (l >= cache_size) {
lxcfs_error("%s\n", "Internal error: truncated write to cache.");
- rv = 0;
- goto err;
+ return 0;
}
cache += l;
@@ -3494,14 +3510,6 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
rv = total_len;
err:
- if (f)
- fclose(f);
- free(line);
- free(cg);
- free(memusage_str);
- free(memswlimit_str);
- free(memswusage_str);
- free(memstat_str);
return rv;
}
From 66c5e84848ba9b93f2ebdf06c34b41ea675124bc Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 21 Feb 2020 15:19:08 +0100
Subject: [PATCH 2/2] bindings: port memory to new cgroup getters and implement
cgroup2 support
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
bindings.c | 169 ++++++++++++++++++++++++++---------------------
cgroups/cgfsng.c | 71 ++++++++++++++++++++
cgroups/cgroup.h | 17 +++++
3 files changed, 183 insertions(+), 74 deletions(-)
diff --git a/bindings.c b/bindings.c
index 31c4ccc..52fbb87 100644
--- a/bindings.c
+++ b/bindings.c
@@ -3177,33 +3177,53 @@ static bool startswith(const char *line, const char *pref)
return false;
}
-static void parse_memstat(char *memstat, unsigned long *cached,
- unsigned long *active_anon, unsigned long *inactive_anon,
- unsigned long *active_file, unsigned long *inactive_file,
- unsigned long *unevictable, unsigned long *shmem)
+/* Note that "memory.stat" in cgroup2 is hierarchical by default. */
+static void parse_memstat(int version,
+ char *memstat,
+ unsigned long *cached,
+ unsigned long *active_anon,
+ unsigned long *inactive_anon,
+ unsigned long *active_file,
+ unsigned long *inactive_file,
+ unsigned long *unevictable,
+ unsigned long *shmem)
{
char *eol;
while (*memstat) {
- if (startswith(memstat, "total_cache")) {
+ if (startswith(memstat, is_unified_controller(version)
+ ? "cache"
+ : "total_cache")) {
sscanf(memstat + 11, "%lu", cached);
*cached /= 1024;
- } else if (startswith(memstat, "total_active_anon")) {
+ } else if (startswith(memstat, is_unified_controller(version)
+ ? "active_anon"
+ : "total_active_anon")) {
sscanf(memstat + 17, "%lu", active_anon);
*active_anon /= 1024;
- } else if (startswith(memstat, "total_inactive_anon")) {
+ } else if (startswith(memstat, is_unified_controller(version)
+ ? "inactive_anon"
+ : "total_inactive_anon")) {
sscanf(memstat + 19, "%lu", inactive_anon);
*inactive_anon /= 1024;
- } else if (startswith(memstat, "total_active_file")) {
+ } else if (startswith(memstat, is_unified_controller(version)
+ ? "active_file"
+ : "total_active_file")) {
sscanf(memstat + 17, "%lu", active_file);
*active_file /= 1024;
- } else if (startswith(memstat, "total_inactive_file")) {
+ } else if (startswith(memstat, is_unified_controller(version)
+ ? "inactive_file"
+ : "total_inactive_file")) {
sscanf(memstat + 19, "%lu", inactive_file);
*inactive_file /= 1024;
- } else if (startswith(memstat, "total_unevictable")) {
+ } else if (startswith(memstat, is_unified_controller(version)
+ ? "unevictable"
+ : "total_unevictable")) {
sscanf(memstat + 17, "%lu", unevictable);
*unevictable /= 1024;
- } else if (startswith(memstat, "total_shmem")) {
+ } else if (startswith(memstat, is_unified_controller(version)
+ ? "shmem"
+ : "total_shmem")) {
sscanf(memstat + 11, "%lu", shmem);
*shmem /= 1024;
}
@@ -3283,29 +3303,36 @@ int read_file_fuse(const char *path, char *buf, size_t size, struct file_info *d
* FUSE ops for /proc
*/
-static unsigned long get_memlimit(const char *cgroup, const char *file)
+static unsigned long get_memlimit(const char *cgroup, bool swap)
{
+ int ret;
__do_free char *memlimit_str = NULL;
unsigned long memlimit = -1;
- if (cgroup_ops->get(cgroup_ops, "memory", cgroup, file, &memlimit_str))
+ if (swap)
+ ret = cgroup_ops->get_memory_swap_max(cgroup_ops, cgroup, &memlimit_str);
+ else
+ ret = cgroup_ops->get_memory_max(cgroup_ops, cgroup, &memlimit_str);
+ if (ret > 0)
memlimit = strtoul(memlimit_str, NULL, 10);
return memlimit;
}
-static unsigned long get_min_memlimit(const char *cgroup, const char *file)
+static unsigned long get_min_memlimit(const char *cgroup, bool swap)
{
__do_free char *copy = NULL;
unsigned long memlimit = 0;
unsigned long retlimit;
- copy = strdupa(cgroup);
- retlimit = get_memlimit(copy, file);
+ copy = strdup(cgroup);
+ retlimit = get_memlimit(copy, swap);
while (strcmp(copy, "/") != 0) {
- copy = dirname(copy);
- memlimit = get_memlimit(copy, file);
+ char *it = copy;
+
+ it = dirname(it);
+ memlimit = get_memlimit(it, swap);
if (memlimit != -1 && memlimit < retlimit)
retlimit = memlimit;
};
@@ -3316,7 +3343,7 @@ static unsigned long get_min_memlimit(const char *cgroup, const char *file)
static int proc_meminfo_read(char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
- __do_free char *current_cgroup = NULL, *line = NULL,
+ __do_free char *cgroup = NULL, *line = NULL,
*memusage_str = NULL, *memstat_str = NULL,
*memswlimit_str = NULL, *memswusage_str = NULL;
__do_fclose FILE *f = NULL;
@@ -3327,9 +3354,10 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
memswusage = 0, cached = 0, hosttotal = 0, active_anon = 0,
inactive_anon = 0, active_file = 0, inactive_file = 0,
unevictable = 0, shmem = 0, hostswtotal = 0;
- size_t linelen = 0, total_len = 0, rv = 0;
+ size_t linelen = 0, total_len = 0;
char *cache = d->buf;
size_t cache_size = d->buflen;
+ int ret;
if (offset) {
int left;
@@ -3351,32 +3379,33 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
if (initpid <= 1 || is_shared_pidns(initpid))
initpid = fc->pid;
- current_cgroup = get_pid_cgroup(initpid, "memory");
- if (!current_cgroup)
+ cgroup = get_pid_cgroup(initpid, "memory");
+ if (!cgroup)
return read_file_fuse("/proc/meminfo", buf, size, d);
- prune_init_slice(current_cgroup);
+ prune_init_slice(cgroup);
- memlimit = get_min_memlimit(current_cgroup, "memory.limit_in_bytes");
+ memlimit = get_min_memlimit(cgroup, false);
- if (!cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
- "memory.usage_in_bytes", &memusage_str))
+ ret = cgroup_ops->get_memory_current(cgroup_ops, cgroup, &memusage_str);
+ if (ret < 0)
return 0;
- if (!cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
- "memory.stat", &memstat_str))
+ ret = cgroup_ops->get_memory_stats(cgroup_ops, cgroup, &memstat_str);
+ if (ret < 0)
return 0;
+ parse_memstat(ret, memstat_str, &cached, &active_anon, &inactive_anon,
+ &active_file, &inactive_file, &unevictable, &shmem);
/*
* Following values are allowed to fail, because swapaccount might be
* turned off for current kernel.
*/
- if (cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
- "memory.memsw.limit_in_bytes", &memswlimit_str) &&
- cgroup_ops->get(cgroup_ops, "memory", current_cgroup,
- "memory.memsw.usage_in_bytes", &memswusage_str)) {
- memswlimit = get_min_memlimit(current_cgroup,
- "memory.memsw.limit_in_bytes");
+ ret = cgroup_ops->get_memory_swap_max(cgroup_ops, cgroup, &memswlimit_str);
+ if (ret >= 0)
+ ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str);
+ if (ret >= 0) {
+ memswlimit = get_min_memlimit(cgroup, true);
memswusage = strtoul(memswusage_str, NULL, 10);
memswlimit = memswlimit / 1024;
memswusage = memswusage / 1024;
@@ -3386,9 +3415,6 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
memlimit /= 1024;
memusage /= 1024;
- parse_memstat(memstat_str, &cached, &active_anon, &inactive_anon,
- &active_file, &inactive_file, &unevictable, &shmem);
-
f = fopen("/proc/meminfo", "r");
if (!f)
return 0;
@@ -3508,9 +3534,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
if (total_len > size ) total_len = size;
memcpy(buf, d->buf, total_len);
- rv = total_len;
-err:
- return rv;
+ return total_len;
}
/*
@@ -5245,25 +5269,32 @@ static int proc_diskstats_read(char *buf, size_t size, off_t offset,
}
static int proc_swaps_read(char *buf, size_t size, off_t offset,
- struct fuse_file_info *fi)
+ struct fuse_file_info *fi)
{
+ __do_free char *cg = NULL, *memswlimit_str = NULL, *memusage_str = NULL,
+ *memswusage_str = NULL;
struct fuse_context *fc = fuse_get_context();
struct file_info *d = (struct file_info *)fi->fh;
- char *cg = NULL;
- char *memswlimit_str = NULL, *memlimit_str = NULL, *memusage_str = NULL, *memswusage_str = NULL;
- unsigned long memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0, swap_total = 0, swap_free = 0;
- ssize_t total_len = 0, rv = 0;
+ unsigned long memswlimit = 0, memlimit = 0, memusage = 0,
+ memswusage = 0, swap_total = 0, swap_free = 0;
+ ssize_t total_len = 0;
ssize_t l = 0;
char *cache = d->buf;
+ int ret;
if (offset) {
+ int left;
+
if (offset > d->size)
return -EINVAL;
+
if (!d->cached)
return 0;
- int left = d->size - offset;
+
+ left = d->size - offset;
total_len = left > size ? size: left;
memcpy(buf, cache + offset, total_len);
+
return total_len;
}
@@ -5275,19 +5306,20 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
return read_file_fuse("/proc/swaps", buf, size, d);
prune_init_slice(cg);
- memlimit = get_min_memlimit(cg, "memory.limit_in_bytes");
+ memlimit = get_min_memlimit(cg, false);
- if (!cgroup_ops->get(cgroup_ops, "memory", cg, "memory.usage_in_bytes", &memusage_str))
- goto err;
+ ret = cgroup_ops->get_memory_current(cgroup_ops, cg, &memusage_str);
+ if (ret < 0)
+ return 0;
memusage = strtoul(memusage_str, NULL, 10);
- if (cgroup_ops->get(cgroup_ops, "memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str) &&
- cgroup_ops->get(cgroup_ops, "memory", cg, "memory.memsw.limit_in_bytes", &memswlimit_str)) {
-
- memswlimit = get_min_memlimit(cg, "memory.memsw.limit_in_bytes");
+ ret = cgroup_ops->get_memory_swap_max(cgroup_ops, cg, &memswlimit_str);
+ if (ret >= 0)
+ ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cg, &memswusage_str);
+ if (ret >= 0) {
+ memswlimit = get_min_memlimit(cg, true);
memswusage = strtoul(memswusage_str, NULL, 10);
-
swap_total = (memswlimit - memlimit) / 1024;
swap_free = (memswusage - memusage) / 1024;
}
@@ -5296,23 +5328,20 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
/* When no mem + swap limit is specified or swapaccount=0*/
if (!memswlimit) {
- char *line = NULL;
+ __do_free char *line = NULL;
+ __do_fclose FILE *f = NULL;
size_t linelen = 0;
- FILE *f = fopen("/proc/meminfo", "r");
+ f = fopen("/proc/meminfo", "r");
if (!f)
- goto err;
+ return 0;
while (getline(&line, &linelen, f) != -1) {
- if (startswith(line, "SwapTotal:")) {
+ if (startswith(line, "SwapTotal:"))
sscanf(line, "SwapTotal: %8lu kB", &swap_total);
- } else if (startswith(line, "SwapFree:")) {
+ else if (startswith(line, "SwapFree:"))
sscanf(line, "SwapFree: %8lu kB", &swap_free);
- }
}
-
- free(line);
- fclose(f);
}
if (swap_total > 0) {
@@ -5324,8 +5353,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
if (total_len < 0 || l < 0) {
perror("Error writing to cache");
- rv = 0;
- goto err;
+ return 0;
}
d->cached = 1;
@@ -5333,16 +5361,9 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset,
if (total_len > size) total_len = size;
memcpy(buf, d->buf, total_len);
- rv = total_len;
-
-err:
- free(cg);
- free(memswlimit_str);
- free(memlimit_str);
- free(memusage_str);
- free(memswusage_str);
- return rv;
+ return total_len;
}
+
/*
* Find the process pid from cgroup path.
* eg:from /sys/fs/cgroup/cpu/docker/containerid/cgroup.procs to find the process pid.
diff --git a/cgroups/cgfsng.c b/cgroups/cgfsng.c
index c1a6f7e..426ad8a 100644
--- a/cgroups/cgfsng.c
+++ b/cgroups/cgfsng.c
@@ -603,6 +603,69 @@ static bool cgfsng_get(struct cgroup_ops *ops, const char *controller,
return *value != NULL;
}
+static int cgfsng_get_memory(struct cgroup_ops *ops, const char *cgroup,
+ const char *file, char **value)
+{
+ __do_free char *path = NULL;
+ struct hierarchy *h;
+ int ret;
+
+ h = ops->get_hierarchy(ops, "memory");
+ if (!h)
+ return -1;
+
+ if (!is_unified_hierarchy(h)) {
+ if (strcmp(file, "memory.max") == 0)
+ file = "memory.limit_in_bytes";
+ else if (strcmp(file, "memory.swap.max") == 0)
+ file = "memory.memsw.limit_in_bytes";
+ else if (strcmp(file, "memory.swap.current") == 0)
+ file = "memory.memsw.usage_in_bytes";
+ else if (strcmp(file, "memory.current") == 0)
+ file = "memory.usage_in_bytes";
+ ret = CGROUP_SUPER_MAGIC;
+ } else {
+ ret = CGROUP2_SUPER_MAGIC;
+ }
+
+ path = must_make_path(*cgroup == '/' ? "." : "", cgroup, file, NULL);
+ *value = readat_file(h->fd, path);
+ if (!*value)
+ ret = -1;
+
+ return ret;
+}
+
+static int cgfsng_get_memory_current(struct cgroup_ops *ops, const char *cgroup,
+ char **value)
+{
+ return cgfsng_get_memory(ops, cgroup, "memory.current", value);
+}
+
+static int cgfsng_get_memory_swap_current(struct cgroup_ops *ops,
+ const char *cgroup, char **value)
+{
+ return cgfsng_get_memory(ops, cgroup, "memory.swap.current", value);
+}
+
+static int cgfsng_get_memory_max(struct cgroup_ops *ops, const char *cgroup,
+ char **value)
+{
+ return cgfsng_get_memory(ops, cgroup, "memory.max", value);
+}
+
+static int cgfsng_get_memory_swap_max(struct cgroup_ops *ops,
+ const char *cgroup, char **value)
+{
+ return cgfsng_get_memory(ops, cgroup, "memory.swap.max", value);
+}
+
+static int cgfsng_get_memory_stats(struct cgroup_ops *ops, const char *cgroup,
+ char **value)
+{
+ return cgfsng_get_memory(ops, cgroup, "memory.stat", value);
+}
+
/* At startup, parse_hierarchies finds all the info we need about cgroup
* mountpoints and current cgroups, and stores it in @d.
*/
@@ -799,5 +862,13 @@ struct cgroup_ops *cgfsng_ops_init(void)
cgfsng_ops->mount = cgfsng_mount;
cgfsng_ops->nrtasks = cgfsng_nrtasks;
+
+ /* memory */
+ cgfsng_ops->get_memory_stats = cgfsng_get_memory_stats;
+ cgfsng_ops->get_memory_max = cgfsng_get_memory_max;
+ cgfsng_ops->get_memory_swap_max = cgfsng_get_memory_swap_max;
+ cgfsng_ops->get_memory_current = cgfsng_get_memory_current;
+ cgfsng_ops->get_memory_swap_current = cgfsng_get_memory_swap_current;
+
return move_ptr(cgfsng_ops);
}
diff --git a/cgroups/cgroup.h b/cgroups/cgroup.h
index 808e5d0..e367aff 100644
--- a/cgroups/cgroup.h
+++ b/cgroups/cgroup.h
@@ -122,6 +122,18 @@ struct cgroup_ops {
const char *controller);
bool (*get)(struct cgroup_ops *ops, const char *controller,
const char *cgroup, const char *file, char **value);
+
+ /* memory */
+ int (*get_memory_stats)(struct cgroup_ops *ops, const char *cgroup,
+ char **value);
+ int (*get_memory_current)(struct cgroup_ops *ops, const char *cgroup,
+ char **value);
+ int (*get_memory_swap_current)(struct cgroup_ops *ops,
+ const char *cgroup, char **value);
+ int (*get_memory_max)(struct cgroup_ops *ops, const char *cgroup,
+ char **value);
+ int (*get_memory_swap_max)(struct cgroup_ops *ops, const char *cgroup,
+ char **value);
};
extern struct cgroup_ops *cgroup_init(void);
@@ -149,4 +161,9 @@ static inline bool is_unified_hierarchy(const struct hierarchy *h)
return h->version == CGROUP2_SUPER_MAGIC;
}
+static inline bool is_unified_controller(int version)
+{
+ return version == CGROUP2_SUPER_MAGIC;
+}
+
#endif
More information about the lxc-devel
mailing list