The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxcfs/pull/320

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>

From cfb72d52826919885019a3170cc28b4da3641d13 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@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.brau...@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.brau...@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.brau...@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
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to