| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- // SPDX-License-Identifier: GPL-2.0
- #include <linux/stringify.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "fs.h"
- struct cgroupfs_cache_entry {
- char subsys[32];
- char mountpoint[PATH_MAX];
- };
- /* just cache last used one */
- static struct cgroupfs_cache_entry *cached;
- int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
- {
- FILE *fp;
- char *line = NULL;
- size_t len = 0;
- char *p, *path;
- char mountpoint[PATH_MAX];
- if (cached && !strcmp(cached->subsys, subsys)) {
- if (strlen(cached->mountpoint) < maxlen) {
- strcpy(buf, cached->mountpoint);
- return 0;
- }
- return -1;
- }
- fp = fopen("/proc/mounts", "r");
- if (!fp)
- return -1;
- /*
- * in order to handle split hierarchy, we need to scan /proc/mounts
- * and inspect every cgroupfs mount point to find one that has
- * the given subsystem. If we found v1, just use it. If not we can
- * use v2 path as a fallback.
- */
- mountpoint[0] = '\0';
- /*
- * The /proc/mounts has the follow format:
- *
- * <devname> <mount point> <fs type> <options> ...
- *
- */
- while (getline(&line, &len, fp) != -1) {
- /* skip devname */
- p = strchr(line, ' ');
- if (p == NULL)
- continue;
- /* save the mount point */
- path = ++p;
- p = strchr(p, ' ');
- if (p == NULL)
- continue;
- *p++ = '\0';
- /* check filesystem type */
- if (strncmp(p, "cgroup", 6))
- continue;
- if (p[6] == '2') {
- /* save cgroup v2 path */
- strcpy(mountpoint, path);
- continue;
- }
- /* now we have cgroup v1, check the options for subsystem */
- p += 7;
- p = strstr(p, subsys);
- if (p == NULL)
- continue;
- /* sanity check: it should be separated by a space or a comma */
- if (!strchr(" ,", p[-1]) || !strchr(" ,", p[strlen(subsys)]))
- continue;
- strcpy(mountpoint, path);
- break;
- }
- free(line);
- fclose(fp);
- if (!cached)
- cached = calloc(1, sizeof(*cached));
- if (cached) {
- strncpy(cached->subsys, subsys, sizeof(cached->subsys) - 1);
- strcpy(cached->mountpoint, mountpoint);
- }
- if (mountpoint[0] && strlen(mountpoint) < maxlen) {
- strcpy(buf, mountpoint);
- return 0;
- }
- return -1;
- }
|