mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-18 00:58:31 +00:00
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 <xemul@parallels.com> Acked-by: Tycho Andersen <tycho.andersen@canonical.com>
This commit is contained in:
parent
e301b1d56c
commit
bf91821f11
1 changed files with 31 additions and 28 deletions
59
cgroup.c
59
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue