[lxc-devel] [lxcfs/master] proc_fuse: add /proc/slabinfo with slab accounting memcg

loyou on Github lxc-bot at linuxcontainers.org
Thu Dec 10 10:59:15 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 347 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201210/63dc1fcf/attachment.bin>
-------------- next part --------------
From 6cc153e698cc2f8e7cd356d0e6da1f89e8fa984e Mon Sep 17 00:00:00 2001
From: Feng Sun <loyou85 at gmail.com>
Date: Thu, 10 Dec 2020 17:30:54 +0800
Subject: [PATCH] proc_fuse: add /proc/slabinfo with slab accounting memcg

Signed-off-by: Feng Sun <loyou85 at gmail.com>
---
 README.md            |  2 ++
 src/api_extensions.h |  1 +
 src/bindings.h       |  3 ++
 src/cgroups/cgfsng.c | 17 +++++++++
 src/cgroups/cgroup.h |  4 ++-
 src/proc_fuse.c      | 83 ++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 3c638c3..54d3eab 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ such as:
 /proc/stat
 /proc/swaps
 /proc/uptime
+/proc/slabinfo
 /sys/devices/system/cpu/online
 ```
 
@@ -98,6 +99,7 @@ docker run -it -m 256m --memory-swap 256m \
       -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
       -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
       -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
+      -v /var/lib/lxcfs/proc/slabinfo:/proc/slabinfo:rw \
       ubuntu:18.04 /bin/bash
  ```
 
diff --git a/src/api_extensions.h b/src/api_extensions.h
index a4ee0c1..9ee55da 100644
--- a/src/api_extensions.h
+++ b/src/api_extensions.h
@@ -22,6 +22,7 @@ static char *api_extensions[] = {
 	"proc_stat",
 	"proc_swaps",
 	"proc_uptime",
+	"proc_slabinfo",
 	"shared_pidns",
 	"cpuview_daemon",
 	"loadavg_daemon",
diff --git a/src/bindings.h b/src/bindings.h
index e260902..dc0c23e 100644
--- a/src/bindings.h
+++ b/src/bindings.h
@@ -62,6 +62,9 @@ enum lxcfs_virt_t {
 	LXC_TYPE_PROC_LOADAVG,
 #define LXC_TYPE_PROC_LOADAVG_PATH "/proc/loadavg"
 
+	LXC_TYPE_PROC_SLABINFO,
+#define LXC_TYPE_PROC_SLABINFO_PATH "/proc/slabinfo"
+
 	LXC_TYPE_SYS_DEVICES,
 	LXC_TYPE_SYS_DEVICES_SYSTEM,
 	LXC_TYPE_SYS_DEVICES_SYSTEM_CPU,
diff --git a/src/cgroups/cgfsng.c b/src/cgroups/cgfsng.c
index d772f25..f80785f 100644
--- a/src/cgroups/cgfsng.c
+++ b/src/cgroups/cgfsng.c
@@ -632,6 +632,22 @@ static int cgfsng_get_memory_swap_max(struct cgroup_ops *ops,
 	return cgfsng_get_memory(ops, cgroup, "memory.swap.max", value);
 }
 
+static int cgfsng_get_memory_slabinfo_fd(struct cgroup_ops *ops, const char *cgroup)
+{
+	__do_free char *path = NULL;
+	struct hierarchy *h;
+
+	h = ops->get_hierarchy(ops, "memory");
+	if (!h)
+		return -1;
+
+	if (faccessat(h->fd, "memory.kmem.slabinfo", F_OK, 0))
+		return -1;
+
+	path = must_make_path_relative(cgroup, "memory.kmem.slabinfo", NULL);
+	return openat(h->fd, path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+}
+
 static bool cgfsng_can_use_swap(struct cgroup_ops *ops)
 {
 	bool has_swap = false;
@@ -1021,6 +1037,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
 	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;
+	cgfsng_ops->get_memory_slabinfo_fd = cgfsng_get_memory_slabinfo_fd;
 	cgfsng_ops->can_use_swap = cgfsng_can_use_swap;
 
 	/* cpuset */
diff --git a/src/cgroups/cgroup.h b/src/cgroups/cgroup.h
index f4b5d19..c9ea370 100644
--- a/src/cgroups/cgroup.h
+++ b/src/cgroups/cgroup.h
@@ -152,9 +152,11 @@ struct cgroup_ops {
 	int (*get_memory_max)(struct cgroup_ops *ops, const char *cgroup,
 			      char **value);
 	int (*get_memory_swappiness)(struct cgroup_ops *ops, const char *cgroup,
-			      char **value);
+				     char **value);
 	int (*get_memory_swap_max)(struct cgroup_ops *ops, const char *cgroup,
 				   char **value);
+	int (*get_memory_slabinfo_fd)(struct cgroup_ops *ops,
+				      const char *cgroup);
 	bool (*can_use_swap)(struct cgroup_ops *ops);
 
 	/* cpuset */
diff --git a/src/proc_fuse.c b/src/proc_fuse.c
index 9bf963b..3cee526 100644
--- a/src/proc_fuse.c
+++ b/src/proc_fuse.c
@@ -102,7 +102,8 @@ __lxcfs_fuse_ops int proc_getattr(const char *path, struct stat *sb)
 	    strcmp(path, "/proc/stat")		== 0 ||
 	    strcmp(path, "/proc/diskstats")	== 0 ||
 	    strcmp(path, "/proc/swaps")		== 0 ||
-	    strcmp(path, "/proc/loadavg")	== 0) {
+	    strcmp(path, "/proc/loadavg")	== 0 ||
+	    strcmp(path, "/proc/slabinfo")	== 0) {
 		sb->st_size = 4096;
 		sb->st_mode = S_IFREG | 00444;
 		sb->st_nlink = 1;
@@ -124,7 +125,8 @@ __lxcfs_fuse_ops int proc_readdir(const char *path, void *buf,
 	    DIR_FILLER(filler, buf, "uptime",	NULL, 0) != 0 ||
 	    DIR_FILLER(filler, buf, "diskstats",	NULL, 0) != 0 ||
 	    DIR_FILLER(filler, buf, "swaps",	NULL, 0) != 0 ||
-	    DIR_FILLER(filler, buf, "loadavg",	NULL, 0) != 0)
+	    DIR_FILLER(filler, buf, "loadavg",	NULL, 0) != 0 ||
+	    DIR_FILLER(filler, buf, "slabinfo",	NULL, 0) != 0)
 		return -EINVAL;
 
 	return 0;
@@ -166,6 +168,8 @@ __lxcfs_fuse_ops int proc_open(const char *path, struct fuse_file_info *fi)
 		type = LXC_TYPE_PROC_SWAPS;
 	else if (strcmp(path, "/proc/loadavg") == 0)
 		type = LXC_TYPE_PROC_LOADAVG;
+	else if (strcmp(path, "/proc/slabinfo") == 0)
+		type = LXC_TYPE_PROC_SLABINFO;
 	if (type == -1)
 		return -ENOENT;
 
@@ -1397,6 +1401,75 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
 	return total_len;
 }
 
+static int proc_slabinfo_read(char *buf, size_t size, off_t offset,
+			      struct fuse_file_info *fi)
+{
+	__do_free char *cgroup = NULL, *line = NULL;
+	__do_free void *fopen_cache = NULL;
+	__do_fclose FILE *f = NULL;
+	__do_close int fd = -EBADF;
+	struct fuse_context *fc = fuse_get_context();
+	struct file_info *d = INTTYPE_TO_PTR(fi->fh);
+	size_t linelen = 0, total_len = 0;
+	char *cache = d->buf;
+	size_t cache_size = d->buflen;
+	pid_t initpid;
+
+	if (offset) {
+		int left;
+
+		if (offset > d->size)
+			return -EINVAL;
+
+		if (!d->cached)
+			return 0;
+
+		left = d->size - offset;
+		total_len = left > size ? size : left;
+		memcpy(buf, cache + offset, total_len);
+
+		return total_len;
+	}
+
+	initpid = lookup_initpid_in_store(fc->pid);
+	if (initpid <= 1 || is_shared_pidns(initpid))
+		initpid = fc->pid;
+
+	cgroup = get_pid_cgroup(initpid, "memory");
+	if (!cgroup)
+		return read_file_fuse("/proc/slabinfo", buf, size, d);
+
+	prune_init_slice(cgroup);
+
+	fd = cgroup_ops->get_memory_slabinfo_fd(cgroup_ops, cgroup);
+	if (fd < 0)
+		return read_file_fuse("/proc/slabinfo", buf, size, d);
+
+	f = fdopen_cached(fd, "re", &fopen_cache);
+	if (!f)
+		return read_file_fuse("/proc/slabinfo", buf, size, d);
+
+	while (getline(&line, &linelen, f) != -1) {
+		ssize_t l = snprintf(cache, cache_size, "%s", line);
+		if (l < 0)
+			return log_error(0, "Failed to write cache");
+		if (l >= cache_size)
+			return log_error(0, "Write to cache was truncated");
+
+		cache += l;
+		cache_size -= l;
+		total_len += l;
+	}
+
+	d->cached = 1;
+	d->size = total_len;
+	if (total_len > size)
+		total_len = size;
+	memcpy(buf, d->buf, total_len);
+
+	return total_len;
+}
+
 __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
 			       off_t offset, struct fuse_file_info *fi)
 {
@@ -1445,6 +1518,12 @@ __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
 
 		return read_file_fuse_with_offset(LXC_TYPE_PROC_LOADAVG_PATH,
 						  buf, size, offset, f);
+	case LXC_TYPE_PROC_SLABINFO:
+		if (liblxcfs_functional())
+			return proc_slabinfo_read(buf, size, offset, fi);
+
+		return read_file_fuse_with_offset(LXC_TYPE_PROC_SLABINFO_PATH,
+						  buf, size, offset, f);
 	}
 
 	return -EINVAL;


More information about the lxc-devel mailing list