1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/stringify.h>
3*4882a593Smuzhiyun #include <sys/types.h>
4*4882a593Smuzhiyun #include <sys/stat.h>
5*4882a593Smuzhiyun #include <fcntl.h>
6*4882a593Smuzhiyun #include <stdio.h>
7*4882a593Smuzhiyun #include <stdlib.h>
8*4882a593Smuzhiyun #include <string.h>
9*4882a593Smuzhiyun #include "fs.h"
10*4882a593Smuzhiyun
cgroupfs_find_mountpoint(char * buf,size_t maxlen,const char * subsys)11*4882a593Smuzhiyun int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
12*4882a593Smuzhiyun {
13*4882a593Smuzhiyun FILE *fp;
14*4882a593Smuzhiyun char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
15*4882a593Smuzhiyun char path_v1[PATH_MAX + 1], path_v2[PATH_MAX + 2], *path;
16*4882a593Smuzhiyun char *token, *saved_ptr = NULL;
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun fp = fopen("/proc/mounts", "r");
19*4882a593Smuzhiyun if (!fp)
20*4882a593Smuzhiyun return -1;
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /*
23*4882a593Smuzhiyun * in order to handle split hierarchy, we need to scan /proc/mounts
24*4882a593Smuzhiyun * and inspect every cgroupfs mount point to find one that has
25*4882a593Smuzhiyun * perf_event subsystem
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun path_v1[0] = '\0';
28*4882a593Smuzhiyun path_v2[0] = '\0';
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun while (fscanf(fp, "%*s %"__stringify(PATH_MAX)"s %"__stringify(PATH_MAX)"s %"
31*4882a593Smuzhiyun __stringify(PATH_MAX)"s %*d %*d\n",
32*4882a593Smuzhiyun mountpoint, type, tokens) == 3) {
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun if (!path_v1[0] && !strcmp(type, "cgroup")) {
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun token = strtok_r(tokens, ",", &saved_ptr);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun while (token != NULL) {
39*4882a593Smuzhiyun if (subsys && !strcmp(token, subsys)) {
40*4882a593Smuzhiyun strcpy(path_v1, mountpoint);
41*4882a593Smuzhiyun break;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun token = strtok_r(NULL, ",", &saved_ptr);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun if (!path_v2[0] && !strcmp(type, "cgroup2"))
48*4882a593Smuzhiyun strcpy(path_v2, mountpoint);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (path_v1[0] && path_v2[0])
51*4882a593Smuzhiyun break;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun fclose(fp);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if (path_v1[0])
56*4882a593Smuzhiyun path = path_v1;
57*4882a593Smuzhiyun else if (path_v2[0])
58*4882a593Smuzhiyun path = path_v2;
59*4882a593Smuzhiyun else
60*4882a593Smuzhiyun return -1;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (strlen(path) < maxlen) {
63*4882a593Smuzhiyun strcpy(buf, path);
64*4882a593Smuzhiyun return 0;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun return -1;
67*4882a593Smuzhiyun }
68