[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