[lxc-devel] Add support for /proc/swaps

Teemu Grönqvist teemu.gronqvist at net9.fi
Mon Feb 8 09:00:29 UTC 2016


Hello,

I was asked to sign off this. Sign off is below.

Just signed on the mailing list so unfortunately I can't answer to the old thread.

----------------------------------------------------------

Built overhttps://github.com/tssge/lxcfs/commit/50b75e3

Example Output:

[root at lxc-dev <http://lists.linuxcontainers.org/listinfo/lxc-devel>  ~]# lxc-attach -n ubuntuwily --  /bin/cat /proc/swaps
Filename                                Type            Size    Used    Priority
none                                    virtual         1048572 1048572 0

Signed-off-by: Teemu Grönqvist <teemu.gronqvist at net9.fi>
Signed-off-by: Nehal J Wani <nehaljw.kkd1 at gmail.com 
<http://lists.linuxcontainers.org/listinfo/lxc-devel>>
---
  lxcfs.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
  1 file changed, 116 insertions(+), 2 deletions(-)

diff --git a/lxcfs.c b/lxcfs.c
index a561882..9c52862 100644
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -43,6 +43,7 @@ enum {
  	LXC_TYPE_PROC_UPTIME,
  	LXC_TYPE_PROC_STAT,
  	LXC_TYPE_PROC_DISKSTATS,
+	LXC_TYPE_PROC_SWAPS,
  };
  
  struct file_info {
@@ -2394,6 +2395,113 @@ err:
  	return rv;
  }
  
+static int proc_swaps_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 *memswlimit_str = NULL, *memlimit_str = NULL, *memusage_str = NULL, *memswusage_str = NULL,
+             *memswlimit_default_str = NULL, *memswusage_default_str = NULL;
+	unsigned long memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0, swap_total = 0, swap_free = 0;
+	size_t total_len = 0, rv = 0, linelen = 0;
+	char *cache = d->buf;
+	char *line = NULL;
+	FILE *f = NULL;
+
+	if (offset) {
+		if (offset > d->size)
+			return -EINVAL;
+		if (!d->cached)
+			return 0;
+		int left = d->size - offset;
+		total_len = left > size ? size: left;
+		memcpy(buf, cache + offset, total_len);
+		return total_len;
+	}
+
+	cg = get_pid_cgroup(fc->pid, "memory");
+
+	if (!cg)
+		return read_file("/proc/swaps", buf, size, d);
+
+	if (!cgfs_get_value("memory", cg, "memory.limit_in_bytes", &memlimit_str))
+		goto err;
+
+	if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str))
+		goto err;
+
+	memlimit = strtoul(memlimit_str, NULL, 10);
+	memusage = strtoul(memusage_str, NULL, 10);
+
+	if (cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str) &&
+	    cgfs_get_value("memory", cg, "memory.memsw.limit_in_bytes", &memswlimit_str)) {
+
+                /* If swap accounting 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);
+
+                if (!strcmp(memswlimit_str, memswlimit_default_str))
+                    memswlimit = 0;
+                if (!strcmp(memswusage_str, memswusage_default_str))
+                    memswusage = 0;
+
+		swap_total = (memswlimit - memlimit) / 1024;
+		swap_free = (memswusage - memusage) / 1024;
+	}
+
+	total_len = snprintf(d->buf, d->size, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+
+	/* When no mem + swap limit is specified or swapaccount=0*/
+	if (!memswlimit) {
+		f = fopen("/proc/meminfo", "r");
+		if (!f)
+			goto err;
+
+		while (getline(&line, &linelen, f) != -1) {
+			if (startswith(line, "SwapTotal:")) {
+				sscanf(line, "SwapTotal:      %8lu kB", &swap_total);
+			} else if (startswith(line, "SwapFree:")) {
+				sscanf(line, "SwapFree:      %8lu kB", &swap_free);
+			}
+		}
+	}
+
+	if (swap_total > 0) {
+		total_len += snprintf(d->buf + total_len, d->size,
+				 "none%*svirtual\t\t%lu\t%lu\t0\n", 36, " ",
+				 swap_total, swap_free);
+	}
+
+	if (total_len < 0) {
+		perror("Error writing to cache");
+		rv = 0;
+		goto err;
+	}
+
+	d->cached = 1;
+	d->size = (int)total_len;
+
+	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);
+	free(memswusage_default_str);
+	free(memswlimit_default_str);
+	return rv;
+}
+
  /*
   * Read the cpuset.cpus for cg
   * Return the answer in a newly allocated string which must be freed
@@ -2956,7 +3064,8 @@ static int proc_getattr(const char *path, struct stat *sb)
  			strcmp(path, "/proc/cpuinfo") == 0 ||
  			strcmp(path, "/proc/uptime") == 0 ||
  			strcmp(path, "/proc/stat") == 0 ||
-			strcmp(path, "/proc/diskstats") == 0) {
+			strcmp(path, "/proc/diskstats") == 0 ||
+			strcmp(path, "/proc/swaps") == 0) {
  		sb->st_size = 0;
  		sb->st_mode = S_IFREG | 00444;
  		sb->st_nlink = 1;
@@ -2973,7 +3082,8 @@ static int proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off
  				filler(buf, "meminfo", NULL, 0) != 0 ||
  				filler(buf, "stat", NULL, 0) != 0 ||
  				filler(buf, "uptime", NULL, 0) != 0 ||
-				filler(buf, "diskstats", NULL, 0) != 0)
+				filler(buf, "diskstats", NULL, 0) != 0 ||
+				filler(buf, "swaps", NULL, 0) != 0)
  		return -EINVAL;
  	return 0;
  }
@@ -2993,6 +3103,8 @@ static int proc_open(const char *path, struct fuse_file_info *fi)
  		type = LXC_TYPE_PROC_STAT;
  	else if (strcmp(path, "/proc/diskstats") == 0)
  		type = LXC_TYPE_PROC_DISKSTATS;
+	else if (strcmp(path, "/proc/swaps") == 0)
+		type = LXC_TYPE_PROC_SWAPS;
  	if (type == -1)
  		return -ENOENT;
  
@@ -3039,6 +3151,8 @@ static int proc_read(const char *path, char *buf, size_t size, off_t offset,
  		return proc_stat_read(buf, size, offset, fi);
  	case LXC_TYPE_PROC_DISKSTATS:
  		return proc_diskstats_read(buf, size, offset, fi);
+	case LXC_TYPE_PROC_SWAPS:
+		return proc_swaps_read(buf, size, offset, fi);
  	default:
  		return -EINVAL;
  	}
-- 
2.5.0



More information about the lxc-devel mailing list