1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/stringify.h>
11 struct cgroupfs_cache_entry
{
13 char mountpoint
[PATH_MAX
];
16 /* just cache last used one */
17 static struct cgroupfs_cache_entry
*cached
;
19 int cgroupfs_find_mountpoint(char *buf
, size_t maxlen
, const char *subsys
)
25 char mountpoint
[PATH_MAX
];
27 if (cached
&& !strcmp(cached
->subsys
, subsys
)) {
28 if (strlen(cached
->mountpoint
) < maxlen
) {
29 strcpy(buf
, cached
->mountpoint
);
35 fp
= fopen("/proc/mounts", "r");
40 * in order to handle split hierarchy, we need to scan /proc/mounts
41 * and inspect every cgroupfs mount point to find one that has
42 * the given subsystem. If we found v1, just use it. If not we can
43 * use v2 path as a fallback.
48 * The /proc/mounts has the follow format:
50 * <devname> <mount point> <fs type> <options> ...
53 while (getline(&line
, &len
, fp
) != -1) {
55 p
= strchr(line
, ' ');
59 /* save the mount point */
67 /* check filesystem type */
68 if (strncmp(p
, "cgroup", 6))
72 /* save cgroup v2 path */
73 strcpy(mountpoint
, path
);
77 /* now we have cgroup v1, check the options for subsystem */
80 p
= strstr(p
, subsys
);
84 /* sanity check: it should be separated by a space or a comma */
85 if (!strchr(" ,", p
[-1]) || !strchr(" ,", p
[strlen(subsys
)]))
88 strcpy(mountpoint
, path
);
95 cached
= calloc(1, sizeof(*cached
));
98 strncpy(cached
->subsys
, subsys
, sizeof(cached
->subsys
) - 1);
99 strcpy(cached
->mountpoint
, mountpoint
);
102 if (mountpoint
[0] && strlen(mountpoint
) < maxlen
) {
103 strcpy(buf
, mountpoint
);