[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