Commit d3be641a authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

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 <tycho.andersen@canonical.com>
Reported-by: 's avatarRoss Boucher <boucher@gmail.com>
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Acked-by: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 5db3f4c3
...@@ -188,7 +188,7 @@ static struct cg_set *get_cg_set(struct list_head *ctls, unsigned int n_ctls) ...@@ -188,7 +188,7 @@ static struct cg_set *get_cg_set(struct list_head *ctls, unsigned int n_ctls)
return cs; 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)); struct cg_controller *nc = xmalloc(sizeof(*nc));
if (!nc) if (!nc)
...@@ -208,7 +208,6 @@ struct cg_controller *new_controller(const char *name, int heirarchy) ...@@ -208,7 +208,6 @@ struct cg_controller *new_controller(const char *name, int heirarchy)
} }
nc->n_controllers = 1; nc->n_controllers = 1;
nc->heirarchy = heirarchy;
nc->n_heads = 0; nc->n_heads = 0;
INIT_LIST_HEAD(&nc->heads); INIT_LIST_HEAD(&nc->heads);
...@@ -218,7 +217,7 @@ struct cg_controller *new_controller(const char *name, int heirarchy) ...@@ -218,7 +217,7 @@ struct cg_controller *new_controller(const char *name, int heirarchy)
int parse_cg_info(void) int parse_cg_info(void)
{ {
if (parse_cgroups(&cgroups, &n_cgroups) < 0) if (collect_controllers(&cgroups, &n_cgroups) < 0)
return -1; return -1;
return 0; return 0;
...@@ -522,7 +521,7 @@ static int collect_cgroups(struct list_head *ctls) ...@@ -522,7 +521,7 @@ static int collect_cgroups(struct list_head *ctls)
pr_err("controller %s not found\n", cc->name); pr_err("controller %s not found\n", cc->name);
return -1; return -1;
} else { } 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); list_add_tail(&nc->l, &cg->l);
n_cgroups++; n_cgroups++;
current_controller = nc; current_controller = nc;
......
...@@ -40,7 +40,6 @@ struct cgroup_dir { ...@@ -40,7 +40,6 @@ struct cgroup_dir {
* The heads are subdirectories organized in their tree format. * The heads are subdirectories organized in their tree format.
*/ */
struct cg_controller { struct cg_controller {
int heirarchy;
unsigned int n_controllers; unsigned int n_controllers;
char **controllers; char **controllers;
...@@ -51,7 +50,7 @@ struct cg_controller { ...@@ -51,7 +50,7 @@ struct cg_controller {
/* for cgroup list in cgroup.c */ /* for cgroup list in cgroup.c */
struct list_head l; 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 */ /* parse all global cgroup information into structures */
int parse_cg_info(void); int parse_cg_info(void);
......
...@@ -180,7 +180,7 @@ struct cg_ctl { ...@@ -180,7 +180,7 @@ struct cg_ctl {
extern int parse_task_cgroup(int pid, struct list_head *l, unsigned int *n); extern int parse_task_cgroup(int pid, struct list_head *l, unsigned int *n);
extern void put_ctls(struct list_head *); 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 */ /* callback for AUFS support */
extern int aufs_parse(struct mount_info *mi); extern int aufs_parse(struct mount_info *mi);
......
...@@ -2015,67 +2015,76 @@ void put_ctls(struct list_head *l) ...@@ -2015,67 +2015,76 @@ void put_ctls(struct list_head *l)
} }
} }
/* Parse and create all the real controllers. This does not include things with /* Parse and create all the real controllers. This does not include things with
* the "name=" prefix, e.g. systemd. * 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; FILE *f;
char buf[1024], name[1024];
int heirarchy, exit_code = -1;
struct cg_controller *cur = NULL;
f = fopen_proc(PROC_GEN, "cgroups"); f = fopen_proc(PROC_SELF, "cgroup");
if (!f) { if (f == NULL)
pr_perror("failed opening /proc/cgroups");
return -1; return -1;
}
/* throw away the header */ while (fgets(buf, BUF_SIZE, f)) {
if (!fgets(buf, 1024, f)) struct cg_controller *nc = NULL;
goto out; char *controllers, *off;
while (fgets(buf, 1024, f)) { controllers = strchr(buf, ':');
char *n; if (!controllers) {
char found = 0; pr_err("Unable to parse \"%s\"\n", buf);
goto err;
}
controllers++;
if (sscanf(buf, "%s %d", name, &heirarchy) != 2) { off = strchr(controllers, ':');
pr_err("Unable to parse: %s\n", buf); if (!off) {
goto out; pr_err("Unable to parse \"%s\"\n", buf);
goto err;
} }
list_for_each_entry(cur, cgroups, l) { *off = '\0';
if (cur->heirarchy == heirarchy) { 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; void *m;
char *n;
found = 1; nc->n_controllers++;
cur->n_controllers++; m = xrealloc(nc->controllers, sizeof(char *) * nc->n_controllers);
m = xrealloc(cur->controllers, sizeof(char *) * cur->n_controllers);
if (!m) if (!m)
goto out; goto err;
cur->controllers = m; nc->controllers = m;
n = xstrdup(name); n = xstrdup(controllers);
if (!n) if (!n)
goto out; goto err;
cur->controllers[cur->n_controllers-1] = n; nc->controllers[nc->n_controllers-1] = n;
break;
} }
}
skip:
if (!found) { if (!off)
struct cg_controller *nc = new_controller(name, heirarchy); break;
if (!nc) controllers = off + 1;
goto out;
list_add_tail(&nc->l, &cur->l);
(*n_cgroups)++;
} }
} }
exit_code = 0; exit_code = 0;
out: err:
fclose(f); fclose(f);
return exit_code; return exit_code;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment