diff --git a/cgroup.c b/cgroup.c index 10ecd272c..57ee989bb 100644 --- a/cgroup.c +++ b/cgroup.c @@ -168,48 +168,10 @@ int parse_cg_info(void) return 0; } -static int get_cgroup_mount_point(const char *controller, char *path) -{ - struct mount_info *m; - char name[1024]; - - for (m = cg_mntinfo; m != NULL; m = m->next) { - if (strcmp(m->fstype->name, "cgroup") == 0) { - char *start, *end; - - start = strstr(m->options, "name="); - if (start) { - /* strlen("name=") == 5 */ - start = start + 5; - - end = strstr(start, ","); - if (end) { - strncpy(name, start, end - start); - name[end - start] = '\0'; - } else - strcpy(name, start); - } else { - start = strrchr(m->mountpoint, '/'); - if (!start) { - pr_err("bad path %s\n", m->mountpoint); - return -1; - } - strcpy(name, start+1); - } - - if (strcmp(name, controller) == 0) { - /* skip the leading '.' in mountpoint */ - strcpy(path, m->mountpoint + 1); - return 0; - } - } - } - - return -1; -} /* Check that co-mounted controllers from /proc/cgroups (e.g. cpu and cpuacct) - * are contained in a name from /proc/self/cgroup (e.g. cpu,cpuacct). */ + * are contained in a comma separated string (e.g. from /proc/self/cgroup or + * mount options). */ bool cgroup_contains(char **controllers, unsigned int n_controllers, char *name) { unsigned int i; @@ -235,6 +197,33 @@ bool cgroup_contains(char **controllers, unsigned int n_controllers, char *name) return all_match && n_controllers > 0; } +static int get_cgroup_mount_point(char *controller, char *path) +{ + struct mount_info *m; + char **names; + int n_names, i, ret = -1; + + split(controller, ',', &names, &n_names); + if (!names) + return -1; + + for (m = cg_mntinfo; m != NULL; m = m->next) { + if (strcmp(m->fstype->name, "cgroup") == 0 && + cgroup_contains(names, n_names, m->options)) { + /* skip the leading '.' in mountpoint */ + strcpy(path, m->mountpoint + 1); + ret = 0; + goto out; + } + } + +out: + for (i = 0; i < n_names; i++) + xfree(names[i]); + xfree(names); + return ret; +} + /* This is for use in add_cgroup() as additional arguments for the ftw() * callback */ static struct cg_controller *current_controller; @@ -366,6 +355,8 @@ static int collect_cgroups(struct list_head *ctls) char opts[1024]; temp_mount = true; + pr_info("Couldn't find mount point for %s mounting..\n", name); + if (mkdtemp(prefix) == NULL) { pr_perror("can't make dir for cg mounts\n"); return -1; diff --git a/include/util.h b/include/util.h index 522fc339b..7d16aa2a2 100644 --- a/include/util.h +++ b/include/util.h @@ -315,4 +315,5 @@ int mkdirp(const char *path); */ bool is_path_prefix(const char *path, const char *prefix); FILE *fopenat(int dirfd, char *path, char *cflags); +void split(char *str, char token, char ***out, int *n); #endif /* __CR_UTIL_H__ */ diff --git a/util.c b/util.c index 2553adc9a..288f1db1f 100644 --- a/util.c +++ b/util.c @@ -755,3 +755,50 @@ FILE *fopenat(int dirfd, char *path, char *cflags) return fdopen(tmp, cflags); } + +void split(char *str, char token, char ***out, int *n) +{ + int i; + char *cur; + + *n = 0; + for (cur = str; cur != NULL; cur = strchr(cur, token)) { + (*n)++; + cur++; + } + + + *out = xmalloc((*n) * sizeof(char *)); + if (!*out) { + *n = -1; + return; + + } + + cur = str; + i = 0; + do { + char *prev = cur; + cur = strchr(cur, token); + + if (cur) + *cur = '\0'; + (*out)[i] = xstrdup(prev); + if (cur) { + *cur = token; + cur++; + } + + if (!(*out)[i]) { + int j; + for (j = 0; j < i; j++) + xfree((*out)[j]); + xfree(out); + *out = NULL; + *n = -1; + return; + } + + i++; + } while(cur); +}