Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools api fs: Diet cgroupfs_find_mountpoint()

Reduce the number of buffers and hopefully make it more efficient. :)

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lore.kernel.org/lkml/20201216090556.813996-2-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
6fd99b7f 27ab1c1c

+45 -25
+45 -25
tools/lib/api/fs/cgroup.c
··· 11 11 int cgroupfs_find_mountpoint(char *buf, size_t maxlen, const char *subsys) 12 12 { 13 13 FILE *fp; 14 - char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1]; 15 - char path_v2[PATH_MAX + 1]; 16 - char *token, *saved_ptr = NULL; 14 + char *line = NULL; 15 + size_t len = 0; 16 + char *p, *path; 17 + char mountpoint[PATH_MAX]; 17 18 18 19 fp = fopen("/proc/mounts", "r"); 19 20 if (!fp) ··· 26 25 * the given subsystem. If we found v1, just use it. If not we can 27 26 * use v2 path as a fallback. 28 27 */ 29 - path_v2[0] = '\0'; 28 + mountpoint[0] = '\0'; 30 29 31 - while (fscanf(fp, "%*s %"__stringify(PATH_MAX)"s %"__stringify(PATH_MAX)"s %" 32 - __stringify(PATH_MAX)"s %*d %*d\n", 33 - mountpoint, type, tokens) == 3) { 30 + /* 31 + * The /proc/mounts has the follow format: 32 + * 33 + * <devname> <mount point> <fs type> <options> ... 34 + * 35 + */ 36 + while (getline(&line, &len, fp) != -1) { 37 + /* skip devname */ 38 + p = strchr(line, ' '); 39 + if (p == NULL) 40 + continue; 34 41 35 - if (!strcmp(type, "cgroup")) { 42 + /* save the mount point */ 43 + path = ++p; 44 + p = strchr(p, ' '); 45 + if (p == NULL) 46 + continue; 36 47 37 - token = strtok_r(tokens, ",", &saved_ptr); 48 + *p++ = '\0'; 38 49 39 - while (token != NULL) { 40 - if (subsys && !strcmp(token, subsys)) { 41 - /* found */ 42 - fclose(fp); 50 + /* check filesystem type */ 51 + if (strncmp(p, "cgroup", 6)) 52 + continue; 43 53 44 - if (strlen(mountpoint) < maxlen) { 45 - strcpy(buf, mountpoint); 46 - return 0; 47 - } 48 - return -1; 49 - } 50 - token = strtok_r(NULL, ",", &saved_ptr); 51 - } 54 + if (p[6] == '2') { 55 + /* save cgroup v2 path */ 56 + strcpy(mountpoint, path); 57 + continue; 52 58 } 53 59 54 - if (!strcmp(type, "cgroup2")) 55 - strcpy(path_v2, mountpoint); 60 + /* now we have cgroup v1, check the options for subsystem */ 61 + p += 7; 62 + 63 + p = strstr(p, subsys); 64 + if (p == NULL) 65 + continue; 66 + 67 + /* sanity check: it should be separated by a space or a comma */ 68 + if (!strchr(" ,", p[-1]) || !strchr(" ,", p[strlen(subsys)])) 69 + continue; 70 + 71 + strcpy(mountpoint, path); 72 + break; 56 73 } 74 + free(line); 57 75 fclose(fp); 58 76 59 - if (path_v2[0] && strlen(path_v2) < maxlen) { 60 - strcpy(buf, path_v2); 77 + if (mountpoint[0] && strlen(mountpoint) < maxlen) { 78 + strcpy(buf, mountpoint); 61 79 return 0; 62 80 } 63 81 return -1;