[lxc-devel] [PATCH v2] Fix Busted Swap Accounting

Nehal J Wani nehaljw.kkd1 at gmail.com
Tue Jan 19 19:07:16 UTC 2016


When no limit is specified using lxc.cgroup.memory.memsw.limit_in_bytes,
overflow occurs while calculating Swap{Total,Free}. Commit a2de34b tried
to fix this, but introduced another bug, wherein if
memory.memsw.limit_in_bytes >= memory.limit_in_bytes, then Swap{Total,Free}
are not shown as expected.

When a container is spawned with the settings...

lxc.cgroup.memory.limit_in_bytes = 256M
lxc.cgroup.memory.memsw.limit_in_bytes = 512M

...I find that inside the container, we have:

[root at test ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           256         24        231          6          0         20
-/+ buffers/cache:          3        252
Swap:         1023          0       1023

The total swap should have been 256MB, but it is being
shown as ~1GB (same as host). Basically, the memsw setting is being
ignored.

This patch attempts to fix this by assuming that the when no limit is
specified, the value is same that as of cgroup /

Signed-off-by: Nehal J Wani <nehaljw.kkd1 at gmail.com>
---
 lxcfs.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/lxcfs.c b/lxcfs.c
index 9859171..d17e1ed 100644
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -1924,7 +1924,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
 	struct file_info *d = (struct file_info *)fi->fh;
 	char *cg;
 	char *memusage_str = NULL, *memstat_str = NULL,
-		*memswlimit_str = NULL, *memswusage_str = NULL;
+		*memswlimit_str = NULL, *memswusage_str = NULL,
+		*memswlimit_default_str = NULL, *memswusage_default_str = NULL;
 	unsigned long memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0,
 		cached = 0, hosttotal = 0;
 	char *line = NULL;
@@ -1954,26 +1955,33 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
 	if (!cgfs_get_value("memory", cg, "memory.stat", &memstat_str))
 		goto err;
 
-	memusage = strtoul(memusage_str, NULL, 10);
-	memlimit /= 1024;
-	memusage /= 1024;
-
 	// Following values are allowed to fail, because swapaccount might be turned
 	// off for current kernel
 	if(cgfs_get_value("memory", cg, "memory.memsw.limit_in_bytes", &memswlimit_str) &&
 		cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str))
 	{
+		/* If swapaccounting is turned on, then default value is assumed to be that of cgroup / */
+		if (!cgfs_get_value("memory", "/", "memory.memsw.limit_in_bytes", &memswlimit_default_str))
+			goto err;
+		if (!cgfs_get_value("memory", "/", "memory.memsw.usage_in_bytes", &memswusage_default_str))
+			goto err;
+
 		memswlimit = strtoul(memswlimit_str, NULL, 10);
 		memswusage = strtoul(memswusage_str, NULL, 10);
-		memswlimit /= 1024;
-		memswusage /= 1024;
-		if (memswlimit >= memlimit)
+
+		if (!strcmp(memswlimit_str, memswlimit_default_str))
 			memswlimit = 0;
-		if (memswusage >= memlimit)
+		if (!strcmp(memswusage_str, memswusage_default_str))
 			memswusage = 0;
 
+		memswlimit = memswlimit / 1024;
+		memswusage = memswusage / 1024;
 	}
-	
+
+	memusage = strtoul(memusage_str, NULL, 10);
+	memlimit /= 1024;
+	memusage /= 1024;
+
 	get_mem_cached(memstat_str, &cached);
 
 	f = fopen("/proc/meminfo", "r");
@@ -2049,6 +2057,8 @@ err:
 	free(memswlimit_str);
 	free(memswusage_str);
 	free(memstat_str);
+	free(memswlimit_default_str);
+	free(memswusage_default_str);
 	return rv;
 }
 
-- 
2.5.0



More information about the lxc-devel mailing list