Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/stringify.h>
0003 #include <sys/types.h>
0004 #include <sys/stat.h>
0005 #include <fcntl.h>
0006 #include <stdio.h>
0007 #include <stdlib.h>
0008 #include <string.h>
0009 #include "fs.h"
0010 
0011 struct cgroupfs_cache_entry {
0012     char    subsys[32];
0013     char    mountpoint[PATH_MAX];
0014 };
0015 
0016 /* just cache last used one */
0017 static struct cgroupfs_cache_entry cached;
0018 
0019 int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
0020 {
0021     FILE *fp;
0022     char *line = NULL;
0023     size_t len = 0;
0024     char *p, *path;
0025     char mountpoint[PATH_MAX];
0026 
0027     if (!strcmp(cached.subsys, subsys)) {
0028         if (strlen(cached.mountpoint) < maxlen) {
0029             strcpy(buf, cached.mountpoint);
0030             return 0;
0031         }
0032         return -1;
0033     }
0034 
0035     fp = fopen("/proc/mounts", "r");
0036     if (!fp)
0037         return -1;
0038 
0039     /*
0040      * in order to handle split hierarchy, we need to scan /proc/mounts
0041      * and inspect every cgroupfs mount point to find one that has
0042      * the given subsystem.  If we found v1, just use it.  If not we can
0043      * use v2 path as a fallback.
0044      */
0045     mountpoint[0] = '\0';
0046 
0047     /*
0048      * The /proc/mounts has the follow format:
0049      *
0050      *   <devname> <mount point> <fs type> <options> ...
0051      *
0052      */
0053     while (getline(&line, &len, fp) != -1) {
0054         /* skip devname */
0055         p = strchr(line, ' ');
0056         if (p == NULL)
0057             continue;
0058 
0059         /* save the mount point */
0060         path = ++p;
0061         p = strchr(p, ' ');
0062         if (p == NULL)
0063             continue;
0064 
0065         *p++ = '\0';
0066 
0067         /* check filesystem type */
0068         if (strncmp(p, "cgroup", 6))
0069             continue;
0070 
0071         if (p[6] == '2') {
0072             /* save cgroup v2 path */
0073             strcpy(mountpoint, path);
0074             continue;
0075         }
0076 
0077         /* now we have cgroup v1, check the options for subsystem */
0078         p += 7;
0079 
0080         p = strstr(p, subsys);
0081         if (p == NULL)
0082             continue;
0083 
0084         /* sanity check: it should be separated by a space or a comma */
0085         if (!strchr(" ,", p[-1]) || !strchr(" ,", p[strlen(subsys)]))
0086             continue;
0087 
0088         strcpy(mountpoint, path);
0089         break;
0090     }
0091     free(line);
0092     fclose(fp);
0093 
0094     strncpy(cached.subsys, subsys, sizeof(cached.subsys) - 1);
0095     strcpy(cached.mountpoint, mountpoint);
0096 
0097     if (mountpoint[0] && strlen(mountpoint) < maxlen) {
0098         strcpy(buf, mountpoint);
0099         return 0;
0100     }
0101     return -1;
0102 }