From d3be641acdfc29174524252668029b2b52cb2046 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Fri, 11 Sep 2015 18:35:00 +0300 Subject: [PATCH] cgroups: get controllers from /proc/self/cgroups (v2) Some controllers can be disabled in kernel options. In this case they are shown in /proc/cgroups, but they could not be mounted. All enabled controllers can be collected from /proc/self/cgroup. https://github.com/xemul/criu/issues/28 v2: ',' is used to separate controllers Cc: Tycho Andersen Reported-by: Ross Boucher Signed-off-by: Andrey Vagin Acked-by: Tycho Andersen Signed-off-by: Pavel Emelyanov --- cgroup.c | 7 ++-- include/cgroup.h | 3 +- include/proc_parse.h | 2 +- proc_parse.c | 87 ++++++++++++++++++++++++-------------------- 4 files changed, 53 insertions(+), 46 deletions(-) diff --git a/cgroup.c b/cgroup.c index 10009be87..7bdccf883 100644 --- a/cgroup.c +++ b/cgroup.c @@ -188,7 +188,7 @@ static struct cg_set *get_cg_set(struct list_head *ctls, unsigned int n_ctls) return cs; } -struct cg_controller *new_controller(const char *name, int heirarchy) +struct cg_controller *new_controller(const char *name) { struct cg_controller *nc = xmalloc(sizeof(*nc)); if (!nc) @@ -208,7 +208,6 @@ struct cg_controller *new_controller(const char *name, int heirarchy) } nc->n_controllers = 1; - nc->heirarchy = heirarchy; nc->n_heads = 0; INIT_LIST_HEAD(&nc->heads); @@ -218,7 +217,7 @@ struct cg_controller *new_controller(const char *name, int heirarchy) int parse_cg_info(void) { - if (parse_cgroups(&cgroups, &n_cgroups) < 0) + if (collect_controllers(&cgroups, &n_cgroups) < 0) return -1; return 0; @@ -522,7 +521,7 @@ static int collect_cgroups(struct list_head *ctls) pr_err("controller %s not found\n", cc->name); return -1; } else { - struct cg_controller *nc = new_controller(cc->name, -1); + struct cg_controller *nc = new_controller(cc->name); list_add_tail(&nc->l, &cg->l); n_cgroups++; current_controller = nc; diff --git a/include/cgroup.h b/include/cgroup.h index 14fef6745..37ba3cbf5 100644 --- a/include/cgroup.h +++ b/include/cgroup.h @@ -40,7 +40,6 @@ struct cgroup_dir { * The heads are subdirectories organized in their tree format. */ struct cg_controller { - int heirarchy; unsigned int n_controllers; char **controllers; @@ -51,7 +50,7 @@ struct cg_controller { /* for cgroup list in cgroup.c */ struct list_head l; }; -struct cg_controller *new_controller(const char *name, int heirarchy); +struct cg_controller *new_controller(const char *name); /* parse all global cgroup information into structures */ int parse_cg_info(void); diff --git a/include/proc_parse.h b/include/proc_parse.h index b4fb57d11..92fc47706 100644 --- a/include/proc_parse.h +++ b/include/proc_parse.h @@ -180,7 +180,7 @@ struct cg_ctl { extern int parse_task_cgroup(int pid, struct list_head *l, unsigned int *n); extern void put_ctls(struct list_head *); -int parse_cgroups(struct list_head *cgroups, unsigned int *n_cgroups); +int collect_controllers(struct list_head *cgroups, unsigned int *n_cgroups); /* callback for AUFS support */ extern int aufs_parse(struct mount_info *mi); diff --git a/proc_parse.c b/proc_parse.c index cf70a92d0..e6c305023 100644 --- a/proc_parse.c +++ b/proc_parse.c @@ -2015,67 +2015,76 @@ void put_ctls(struct list_head *l) } } - /* Parse and create all the real controllers. This does not include things with * the "name=" prefix, e.g. systemd. */ -int parse_cgroups(struct list_head *cgroups, unsigned int *n_cgroups) +int collect_controllers(struct list_head *cgroups, unsigned int *n_cgroups) { + int exit_code = -1; FILE *f; - char buf[1024], name[1024]; - int heirarchy, exit_code = -1; - struct cg_controller *cur = NULL; - f = fopen_proc(PROC_GEN, "cgroups"); - if (!f) { - pr_perror("failed opening /proc/cgroups"); + f = fopen_proc(PROC_SELF, "cgroup"); + if (f == NULL) return -1; - } - /* throw away the header */ - if (!fgets(buf, 1024, f)) - goto out; + while (fgets(buf, BUF_SIZE, f)) { + struct cg_controller *nc = NULL; + char *controllers, *off; - while (fgets(buf, 1024, f)) { - char *n; - char found = 0; - - if (sscanf(buf, "%s %d", name, &heirarchy) != 2) { - pr_err("Unable to parse: %s\n", buf); - goto out; + controllers = strchr(buf, ':'); + if (!controllers) { + pr_err("Unable to parse \"%s\"\n", buf); + goto err; } - list_for_each_entry(cur, cgroups, l) { - if (cur->heirarchy == heirarchy) { + controllers++; + + off = strchr(controllers, ':'); + if (!off) { + pr_err("Unable to parse \"%s\"\n", buf); + goto err; + } + *off = '\0'; + while (1) { + off = strchr(controllers, ','); + if (off) + *off = '\0'; + + if (!strncmp("name=", controllers, 5)) + goto skip; + + if (!nc) { + nc = new_controller(controllers); + if (!nc) + goto err; + list_add_tail(&nc->l, cgroups); + (*n_cgroups)++; + } else { void *m; + char *n; - found = 1; - cur->n_controllers++; - m = xrealloc(cur->controllers, sizeof(char *) * cur->n_controllers); + nc->n_controllers++; + m = xrealloc(nc->controllers, sizeof(char *) * nc->n_controllers); if (!m) - goto out; + goto err; - cur->controllers = m; + nc->controllers = m; - n = xstrdup(name); + n = xstrdup(controllers); if (!n) - goto out; + goto err; - cur->controllers[cur->n_controllers-1] = n; - break; + nc->controllers[nc->n_controllers-1] = n; } - } - - if (!found) { - struct cg_controller *nc = new_controller(name, heirarchy); - if (!nc) - goto out; - list_add_tail(&nc->l, &cur->l); - (*n_cgroups)++; + +skip: + if (!off) + break; + controllers = off + 1; } } exit_code = 0; -out: +err: fclose(f); return exit_code; }