[CRIU] [PATCH] cgroups: get controllers from /proc/self/cgroups (v2)
Andrey Vagin
avagin at openvz.org
Fri Sep 11 08:35:46 PDT 2015
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 at canonical.com>
Reported-by: Ross Boucher <boucher at gmail.com>
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cgroup.c | 7 ++---
include/cgroup.h | 3 +-
include/proc_parse.h | 2 +-
proc_parse.c | 85 +++++++++++++++++++++++++++++-----------------------
4 files changed, 52 insertions(+), 45 deletions(-)
diff --git a/cgroup.c b/cgroup.c
index 10009be..7bdccf8 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 14fef67..37ba3cb 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 b4fb57d..92fc477 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 fad6bae..1547063 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -2024,67 +2024,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;
+ controllers = strchr(buf, ':');
+ if (!controllers) {
+ pr_err("Unable to parse \"%s\"\n", buf);
+ goto err;
+ }
+ controllers++;
- if (sscanf(buf, "%s %d", name, &heirarchy) != 2) {
- pr_err("Unable to parse: %s\n", buf);
- goto out;
+ off = strchr(controllers, ':');
+ if (!off) {
+ pr_err("Unable to parse \"%s\"\n", buf);
+ goto err;
}
- list_for_each_entry(cur, cgroups, l) {
- if (cur->heirarchy == heirarchy) {
+ *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;
}
--
2.4.3
More information about the CRIU
mailing list