[CRIU] [PATCH] cg: Fix restoration of tasks into existing cgroups

Pavel Emelyanov xemul at parallels.com
Wed Aug 13 05:24:27 PDT 2014


When we omit the --manage-cgroups on dump the controllers section
in cgroups image lacks the none-d entries (the name=systemd is the
most typical).

If it happens, that init task lives in non-criu cgset (it can be
so if we do --shell-job dump from another terminal and see criu
and root task living in different user.slice systemd cgroups) then
on restore the move_in_cgroup() would fail to lookup the required
controller.

In order to fix this we should still call the collect_cgroups()
on dump, so that it adds the none-d controllers into the list,
but don't dump the dirs tree itself.

The patch looks ugly, but it just moves the current_controller
evaluation from the middle of the loop upwards (and renames the
char *opts variable not to conflict with global opts).

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>

---

diff --git a/cgroup.c b/cgroup.c
index 8308413..ca936e5 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -490,36 +490,10 @@ static int collect_cgroups(struct list_head *ctls)
 	int fd = -1;
 
 	list_for_each_entry(cc, ctls, l) {
-		char path[PATH_MAX], opts[1024];
+		char path[PATH_MAX], mopts[1024];
 		char *name, prefix[] = ".criu.cgmounts.XXXXXX";
 		struct cg_controller *cg;
 
-		if (strstartswith(cc->name, "name=")) {
-			name = cc->name + 5;
-			snprintf(opts, sizeof(opts), "none,%s", cc->name);
-		} else {
-			name = cc->name;
-			snprintf(opts, sizeof(opts), "%s", name);
-		}
-
-		if (mkdtemp(prefix) == NULL) {
-			pr_perror("can't make dir for cg mounts\n");
-			return -1;
-		}
-
-		if (mount("none", prefix, "cgroup", 0, opts) < 0) {
-			pr_perror("couldn't mount %s\n", opts);
-			rmdir(prefix);
-			return -1;
-		}
-
-		fd = open_detach_mount(prefix);
-		if (fd < 0)
-			return -1;
-
-		path_pref_len = snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
-		snprintf(path + path_pref_len, PATH_MAX - path_pref_len, "%s", cc->path);
-
 		current_controller = NULL;
 
 		/* We should get all the "real" (i.e. not name=systemd type)
@@ -546,6 +520,35 @@ static int collect_cgroups(struct list_head *ctls)
 			}
 		}
 
+		if (!opts.manage_cgroups)
+			continue;
+
+		if (strstartswith(cc->name, "name=")) {
+			name = cc->name + 5;
+			snprintf(mopts, sizeof(mopts), "none,%s", cc->name);
+		} else {
+			name = cc->name;
+			snprintf(mopts, sizeof(mopts), "%s", name);
+		}
+
+		if (mkdtemp(prefix) == NULL) {
+			pr_perror("can't make dir for cg mounts\n");
+			return -1;
+		}
+
+		if (mount("none", prefix, "cgroup", 0, mopts) < 0) {
+			pr_perror("couldn't mount %s\n", mopts);
+			rmdir(prefix);
+			return -1;
+		}
+
+		fd = open_detach_mount(prefix);
+		if (fd < 0)
+			return -1;
+
+		path_pref_len = snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
+		snprintf(path + path_pref_len, PATH_MAX - path_pref_len, "%s", cc->path);
+
 		ret = ftw(path, add_cgroup, 4);
 		if (ret < 0) {
 			pr_perror("failed walking %s for empty cgroups\n", path);
@@ -595,7 +598,7 @@ int dump_task_cgroup(struct pstree_item *item, u32 *cg_id)
 		 * The on-stack ctls is moved into cs inside
 		 * the get_cg_set routine.
 		 */
-		if (cs != criu_cgset && opts.manage_cgroups && collect_cgroups(&cs->ctls))
+		if (cs != criu_cgset && collect_cgroups(&cs->ctls))
 			return -1;
 	}
 



More information about the CRIU mailing list