The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxcfs/pull/440

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===

Signed-off-by: Feng Sun <loyo...@gmail.com>
From 6cc153e698cc2f8e7cd356d0e6da1f89e8fa984e Mon Sep 17 00:00:00 2001
From: Feng Sun <loyo...@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 <loyo...@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;
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to