]> git.proxmox.com Git - mirror_lxcfs.git/commitdiff
/proc/meminfo: show the lowest limit amongst our ancestors
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Fri, 30 Oct 2015 23:30:56 +0000 (18:30 -0500)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Sat, 31 Oct 2015 00:46:45 +0000 (19:46 -0500)
If we are in /a/b/c, and b is limited to 500k, then c's limit_in_bytes
will not reflect the 500k, although that will be enforced for us.  So
check our lineage for the lowest limit.

Closes #44

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
lxcfs.c
tests/main.sh
tests/test_meminfo_hierarchy.sh [new file with mode: 0755]

diff --git a/lxcfs.c b/lxcfs.c
index 15859e0e19b66b453fb0016d7d4f8d2eed78c4cf..69d991cf3059562bc46ccc6759793289c4d98a14 100644 (file)
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -1842,13 +1842,43 @@ static int read_file(const char *path, char *buf, size_t size,
  * FUSE ops for /proc
  */
 
  * FUSE ops for /proc
  */
 
+static unsigned long get_memlimit(const char *cgroup)
+{
+       char *memlimit_str = NULL;
+       unsigned long memlimit = -1;
+
+       if (cgm_get_value("memory", cgroup, "memory.limit_in_bytes", &memlimit_str))
+               memlimit = strtoul(memlimit_str, NULL, 10);
+
+       free(memlimit_str);
+
+       return memlimit;
+}
+
+static unsigned long get_min_memlimit(const char *cgroup)
+{
+       char *copy = strdupa(cgroup);
+       unsigned long memlimit = 0, retlimit;
+
+       retlimit = get_memlimit(copy);
+
+       while (strcmp(copy, "/") != 0) {
+               copy = dirname(copy);
+               memlimit = get_memlimit(copy);
+               if (memlimit != -1 && memlimit < retlimit)
+                       retlimit = memlimit;
+       };
+
+       return retlimit;
+}
+
 static int proc_meminfo_read(char *buf, size_t size, off_t offset,
                struct fuse_file_info *fi)
 {
        struct fuse_context *fc = fuse_get_context();
        struct file_info *d = (struct file_info *)fi->fh;
        char *cg;
 static int proc_meminfo_read(char *buf, size_t size, off_t offset,
                struct fuse_file_info *fi)
 {
        struct fuse_context *fc = fuse_get_context();
        struct file_info *d = (struct file_info *)fi->fh;
        char *cg;
-       char *memlimit_str = NULL, *memusage_str = NULL, *memstat_str = NULL;
+       char *memusage_str = NULL, *memstat_str = NULL;
        unsigned long memlimit = 0, memusage = 0, cached = 0, hosttotal = 0;
        char *line = NULL;
        size_t linelen = 0, total_len = 0, rv = 0;
        unsigned long memlimit = 0, memusage = 0, cached = 0, hosttotal = 0;
        char *line = NULL;
        size_t linelen = 0, total_len = 0, rv = 0;
@@ -1871,13 +1901,11 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
        if (!cg)
                return read_file("/proc/meminfo", buf, size, d);
 
        if (!cg)
                return read_file("/proc/meminfo", buf, size, d);
 
-       if (!cgm_get_value("memory", cg, "memory.limit_in_bytes", &memlimit_str))
-               goto err;
+       memlimit = get_min_memlimit(cg);
        if (!cgm_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str))
                goto err;
        if (!cgm_get_value("memory", cg, "memory.stat", &memstat_str))
                goto err;
        if (!cgm_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str))
                goto err;
        if (!cgm_get_value("memory", cg, "memory.stat", &memstat_str))
                goto err;
-       memlimit = strtoul(memlimit_str, NULL, 10);
        memusage = strtoul(memusage_str, NULL, 10);
        memlimit /= 1024;
        memusage /= 1024;
        memusage = strtoul(memusage_str, NULL, 10);
        memlimit /= 1024;
        memusage /= 1024;
@@ -1945,7 +1973,6 @@ err:
                fclose(f);
        free(line);
        free(cg);
                fclose(f);
        free(line);
        free(cg);
-       free(memlimit_str);
        free(memusage_str);
        free(memstat_str);
        return rv;
        free(memusage_str);
        free(memstat_str);
        return rv;
index f736e233a7bd567bbe2bbdbbb7360884ec6149ab..f139576efd176f6a88e26c394ea7a8a2e61ed394 100755 (executable)
@@ -55,5 +55,7 @@ TESTCASE="test_read_proc.sh"
 ${dirname}/test_read_proc.sh
 TESTCASE="cpusetrange"
 ${dirname}/cpusetrange
 ${dirname}/test_read_proc.sh
 TESTCASE="cpusetrange"
 ${dirname}/cpusetrange
+TESTCASE="meminfo hierarchy"
+${dirname}/test_meminfo_hierarchy.sh
 
 FAILED=0
 
 FAILED=0
diff --git a/tests/test_meminfo_hierarchy.sh b/tests/test_meminfo_hierarchy.sh
new file mode 100755 (executable)
index 0000000..20132ce
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+set -eux
+
+LXCFSDIR=${LXCFSDIR:-/var/lib/lxcfs}
+
+cg1=x1.$$
+cg2=x2.$$
+curcg=$(cgm getpidcgroupabs memory $$)
+
+cleanup() {
+       cgm movepidabs memory ${curcg} $$
+       cgm remove memory ${cg1} 1
+       if [ $FAILED -eq 1 ]; then
+               echo "Failed"
+               exit 1
+       fi
+       echo "Passed"
+       exit 0
+}
+
+FAILED=1
+trap cleanup EXIT HUP INT TERM
+
+cgm create memory ${cg1}
+cgm setvalue memory ${cg1} memory.limit_in_bytes 500000000
+cgm movepid memory ${cg1} $$
+m1=`awk '/^MemTotal:/ { print $2 }' /var/lib/lxcfs/proc/meminfo`
+cgm create memory ${cg2}
+cgm movepid memory ${cg2} $$
+m2=`awk '/^MemTotal:/ { print $2 }' /var/lib/lxcfs/proc/meminfo`
+[ $m1 -eq $m2 ]
+
+FAILED=0