cgroup.c 1.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 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"

int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
{
	FILE *fp;
	char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
15
	char path_v2[PATH_MAX + 1];
16 17 18 19 20 21 22 23 24
	char *token, *saved_ptr = NULL;

	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
25 26
	 * the given subsystem.  If we found v1, just use it.  If not we can
	 * use v2 path as a fallback.
27 28 29 30 31 32 33
	 */
	path_v2[0] = '\0';

	while (fscanf(fp, "%*s %"__stringify(PATH_MAX)"s %"__stringify(PATH_MAX)"s %"
				__stringify(PATH_MAX)"s %*d %*d\n",
				mountpoint, type, tokens) == 3) {

34
		if (!strcmp(type, "cgroup")) {
35 36 37 38 39

			token = strtok_r(tokens, ",", &saved_ptr);

			while (token != NULL) {
				if (subsys && !strcmp(token, subsys)) {
40 41 42 43 44 45 46 47
					/* found */
					fclose(fp);

					if (strlen(mountpoint) < maxlen) {
						strcpy(buf, mountpoint);
						return 0;
					}
					return -1;
48 49 50 51 52
				}
				token = strtok_r(NULL, ",", &saved_ptr);
			}
		}

53
		if (!strcmp(type, "cgroup2"))
54 55 56 57
			strcpy(path_v2, mountpoint);
	}
	fclose(fp);

58 59
	if (path_v2[0] && strlen(path_v2) < maxlen) {
		strcpy(buf, path_v2);
60 61 62 63
		return 0;
	}
	return -1;
}