cgroup.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/stringify.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "fs.h"
  10. struct cgroupfs_cache_entry {
  11. char subsys[32];
  12. char mountpoint[PATH_MAX];
  13. };
  14. /* just cache last used one */
  15. static struct cgroupfs_cache_entry *cached;
  16. int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys)
  17. {
  18. FILE *fp;
  19. char *line = NULL;
  20. size_t len = 0;
  21. char *p, *path;
  22. char mountpoint[PATH_MAX];
  23. if (cached && !strcmp(cached->subsys, subsys)) {
  24. if (strlen(cached->mountpoint) < maxlen) {
  25. strcpy(buf, cached->mountpoint);
  26. return 0;
  27. }
  28. return -1;
  29. }
  30. fp = fopen("/proc/mounts", "r");
  31. if (!fp)
  32. return -1;
  33. /*
  34. * in order to handle split hierarchy, we need to scan /proc/mounts
  35. * and inspect every cgroupfs mount point to find one that has
  36. * the given subsystem. If we found v1, just use it. If not we can
  37. * use v2 path as a fallback.
  38. */
  39. mountpoint[0] = '\0';
  40. /*
  41. * The /proc/mounts has the follow format:
  42. *
  43. * <devname> <mount point> <fs type> <options> ...
  44. *
  45. */
  46. while (getline(&line, &len, fp) != -1) {
  47. /* skip devname */
  48. p = strchr(line, ' ');
  49. if (p == NULL)
  50. continue;
  51. /* save the mount point */
  52. path = ++p;
  53. p = strchr(p, ' ');
  54. if (p == NULL)
  55. continue;
  56. *p++ = '\0';
  57. /* check filesystem type */
  58. if (strncmp(p, "cgroup", 6))
  59. continue;
  60. if (p[6] == '2') {
  61. /* save cgroup v2 path */
  62. strcpy(mountpoint, path);
  63. continue;
  64. }
  65. /* now we have cgroup v1, check the options for subsystem */
  66. p += 7;
  67. p = strstr(p, subsys);
  68. if (p == NULL)
  69. continue;
  70. /* sanity check: it should be separated by a space or a comma */
  71. if (!strchr(" ,", p[-1]) || !strchr(" ,", p[strlen(subsys)]))
  72. continue;
  73. strcpy(mountpoint, path);
  74. break;
  75. }
  76. free(line);
  77. fclose(fp);
  78. if (!cached)
  79. cached = calloc(1, sizeof(*cached));
  80. if (cached) {
  81. strncpy(cached->subsys, subsys, sizeof(cached->subsys) - 1);
  82. strcpy(cached->mountpoint, mountpoint);
  83. }
  84. if (mountpoint[0] && strlen(mountpoint) < maxlen) {
  85. strcpy(buf, mountpoint);
  86. return 0;
  87. }
  88. return -1;
  89. }