Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | // 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; } |