From bf91821f11611e5b18c69eca5046b52ebe6d385b Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 13 Aug 2014 16:24:00 +0400 Subject: [PATCH] cg: Fix restoration of tasks into existing cgroups 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 Acked-by: Tycho Andersen --- cgroup.c | 59 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/cgroup.c b/cgroup.c index 8308413d4..ca936e58c 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; }