Skip to content

Commit 1cc68c8

Browse files
author
Christian Brauner
authored
Merge pull request #440 from loyou/master
proc_fuse: add /proc/slabinfo with slab accounting memcg
2 parents 27dd5e9 + 6cc153e commit 1cc68c8

File tree

6 files changed

+107
-3
lines changed

6 files changed

+107
-3
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ such as:
1515
/proc/stat
1616
/proc/swaps
1717
/proc/uptime
18+
/proc/slabinfo
1819
/sys/devices/system/cpu/online
1920
```
2021

@@ -98,6 +99,7 @@ docker run -it -m 256m --memory-swap 256m \
9899
-v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
99100
-v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
100101
-v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
102+
-v /var/lib/lxcfs/proc/slabinfo:/proc/slabinfo:rw \
101103
ubuntu:18.04 /bin/bash
102104
```
103105

src/api_extensions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static char *api_extensions[] = {
2222
"proc_stat",
2323
"proc_swaps",
2424
"proc_uptime",
25+
"proc_slabinfo",
2526
"shared_pidns",
2627
"cpuview_daemon",
2728
"loadavg_daemon",

src/bindings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ enum lxcfs_virt_t {
6262
LXC_TYPE_PROC_LOADAVG,
6363
#define LXC_TYPE_PROC_LOADAVG_PATH "/proc/loadavg"
6464

65+
LXC_TYPE_PROC_SLABINFO,
66+
#define LXC_TYPE_PROC_SLABINFO_PATH "/proc/slabinfo"
67+
6568
LXC_TYPE_SYS_DEVICES,
6669
LXC_TYPE_SYS_DEVICES_SYSTEM,
6770
LXC_TYPE_SYS_DEVICES_SYSTEM_CPU,

src/cgroups/cgfsng.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,22 @@ static int cgfsng_get_memory_swap_max(struct cgroup_ops *ops,
632632
return cgfsng_get_memory(ops, cgroup, "memory.swap.max", value);
633633
}
634634

635+
static int cgfsng_get_memory_slabinfo_fd(struct cgroup_ops *ops, const char *cgroup)
636+
{
637+
__do_free char *path = NULL;
638+
struct hierarchy *h;
639+
640+
h = ops->get_hierarchy(ops, "memory");
641+
if (!h)
642+
return -1;
643+
644+
if (faccessat(h->fd, "memory.kmem.slabinfo", F_OK, 0))
645+
return -1;
646+
647+
path = must_make_path_relative(cgroup, "memory.kmem.slabinfo", NULL);
648+
return openat(h->fd, path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
649+
}
650+
635651
static bool cgfsng_can_use_swap(struct cgroup_ops *ops)
636652
{
637653
bool has_swap = false;
@@ -1021,6 +1037,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
10211037
cgfsng_ops->get_memory_swap_max = cgfsng_get_memory_swap_max;
10221038
cgfsng_ops->get_memory_current = cgfsng_get_memory_current;
10231039
cgfsng_ops->get_memory_swap_current = cgfsng_get_memory_swap_current;
1040+
cgfsng_ops->get_memory_slabinfo_fd = cgfsng_get_memory_slabinfo_fd;
10241041
cgfsng_ops->can_use_swap = cgfsng_can_use_swap;
10251042

10261043
/* cpuset */

src/cgroups/cgroup.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,11 @@ struct cgroup_ops {
152152
int (*get_memory_max)(struct cgroup_ops *ops, const char *cgroup,
153153
char **value);
154154
int (*get_memory_swappiness)(struct cgroup_ops *ops, const char *cgroup,
155-
char **value);
155+
char **value);
156156
int (*get_memory_swap_max)(struct cgroup_ops *ops, const char *cgroup,
157157
char **value);
158+
int (*get_memory_slabinfo_fd)(struct cgroup_ops *ops,
159+
const char *cgroup);
158160
bool (*can_use_swap)(struct cgroup_ops *ops);
159161

160162
/* cpuset */

src/proc_fuse.c

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ __lxcfs_fuse_ops int proc_getattr(const char *path, struct stat *sb)
102102
strcmp(path, "/proc/stat") == 0 ||
103103
strcmp(path, "/proc/diskstats") == 0 ||
104104
strcmp(path, "/proc/swaps") == 0 ||
105-
strcmp(path, "/proc/loadavg") == 0) {
105+
strcmp(path, "/proc/loadavg") == 0 ||
106+
strcmp(path, "/proc/slabinfo") == 0) {
106107
sb->st_size = 4096;
107108
sb->st_mode = S_IFREG | 00444;
108109
sb->st_nlink = 1;
@@ -124,7 +125,8 @@ __lxcfs_fuse_ops int proc_readdir(const char *path, void *buf,
124125
DIR_FILLER(filler, buf, "uptime", NULL, 0) != 0 ||
125126
DIR_FILLER(filler, buf, "diskstats", NULL, 0) != 0 ||
126127
DIR_FILLER(filler, buf, "swaps", NULL, 0) != 0 ||
127-
DIR_FILLER(filler, buf, "loadavg", NULL, 0) != 0)
128+
DIR_FILLER(filler, buf, "loadavg", NULL, 0) != 0 ||
129+
DIR_FILLER(filler, buf, "slabinfo", NULL, 0) != 0)
128130
return -EINVAL;
129131

130132
return 0;
@@ -166,6 +168,8 @@ __lxcfs_fuse_ops int proc_open(const char *path, struct fuse_file_info *fi)
166168
type = LXC_TYPE_PROC_SWAPS;
167169
else if (strcmp(path, "/proc/loadavg") == 0)
168170
type = LXC_TYPE_PROC_LOADAVG;
171+
else if (strcmp(path, "/proc/slabinfo") == 0)
172+
type = LXC_TYPE_PROC_SLABINFO;
169173
if (type == -1)
170174
return -ENOENT;
171175

@@ -1397,6 +1401,75 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset,
13971401
return total_len;
13981402
}
13991403

1404+
static int proc_slabinfo_read(char *buf, size_t size, off_t offset,
1405+
struct fuse_file_info *fi)
1406+
{
1407+
__do_free char *cgroup = NULL, *line = NULL;
1408+
__do_free void *fopen_cache = NULL;
1409+
__do_fclose FILE *f = NULL;
1410+
__do_close int fd = -EBADF;
1411+
struct fuse_context *fc = fuse_get_context();
1412+
struct file_info *d = INTTYPE_TO_PTR(fi->fh);
1413+
size_t linelen = 0, total_len = 0;
1414+
char *cache = d->buf;
1415+
size_t cache_size = d->buflen;
1416+
pid_t initpid;
1417+
1418+
if (offset) {
1419+
int left;
1420+
1421+
if (offset > d->size)
1422+
return -EINVAL;
1423+
1424+
if (!d->cached)
1425+
return 0;
1426+
1427+
left = d->size - offset;
1428+
total_len = left > size ? size : left;
1429+
memcpy(buf, cache + offset, total_len);
1430+
1431+
return total_len;
1432+
}
1433+
1434+
initpid = lookup_initpid_in_store(fc->pid);
1435+
if (initpid <= 1 || is_shared_pidns(initpid))
1436+
initpid = fc->pid;
1437+
1438+
cgroup = get_pid_cgroup(initpid, "memory");
1439+
if (!cgroup)
1440+
return read_file_fuse("/proc/slabinfo", buf, size, d);
1441+
1442+
prune_init_slice(cgroup);
1443+
1444+
fd = cgroup_ops->get_memory_slabinfo_fd(cgroup_ops, cgroup);
1445+
if (fd < 0)
1446+
return read_file_fuse("/proc/slabinfo", buf, size, d);
1447+
1448+
f = fdopen_cached(fd, "re", &fopen_cache);
1449+
if (!f)
1450+
return read_file_fuse("/proc/slabinfo", buf, size, d);
1451+
1452+
while (getline(&line, &linelen, f) != -1) {
1453+
ssize_t l = snprintf(cache, cache_size, "%s", line);
1454+
if (l < 0)
1455+
return log_error(0, "Failed to write cache");
1456+
if (l >= cache_size)
1457+
return log_error(0, "Write to cache was truncated");
1458+
1459+
cache += l;
1460+
cache_size -= l;
1461+
total_len += l;
1462+
}
1463+
1464+
d->cached = 1;
1465+
d->size = total_len;
1466+
if (total_len > size)
1467+
total_len = size;
1468+
memcpy(buf, d->buf, total_len);
1469+
1470+
return total_len;
1471+
}
1472+
14001473
__lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
14011474
off_t offset, struct fuse_file_info *fi)
14021475
{
@@ -1445,6 +1518,12 @@ __lxcfs_fuse_ops int proc_read(const char *path, char *buf, size_t size,
14451518

14461519
return read_file_fuse_with_offset(LXC_TYPE_PROC_LOADAVG_PATH,
14471520
buf, size, offset, f);
1521+
case LXC_TYPE_PROC_SLABINFO:
1522+
if (liblxcfs_functional())
1523+
return proc_slabinfo_read(buf, size, offset, fi);
1524+
1525+
return read_file_fuse_with_offset(LXC_TYPE_PROC_SLABINFO_PATH,
1526+
buf, size, offset, f);
14481527
}
14491528

14501529
return -EINVAL;

0 commit comments

Comments
 (0)