diff --git a/criu/cgroup.c b/criu/cgroup.c index 26f159c74..22e722acf 100644 --- a/criu/cgroup.c +++ b/criu/cgroup.c @@ -186,7 +186,8 @@ int parse_cg_info(void) /* Check that co-mounted controllers from /proc/cgroups (e.g. cpu and cpuacct) * are contained in a comma separated string (e.g. from /proc/self/cgroup or * mount options). */ -static bool cgroup_contains(char **controllers, unsigned int n_controllers, char *name) +static bool cgroup_contains(char **controllers, + unsigned int n_controllers, char *name, u64 *mask) { unsigned int i; bool all_match = true; @@ -201,6 +202,8 @@ static bool cgroup_contains(char **controllers, unsigned int n_controllers, char case '\0': case ',': found = true; + if (mask) + *mask &= ~(1ULL << i); break; } } @@ -557,7 +560,7 @@ static int collect_cgroups(struct list_head *ctls) * controller from parse_cgroups(), so find that controller if * it exists. */ list_for_each_entry(cg, &cgroups, l) { - if (cgroup_contains(cg->controllers, cg->n_controllers, cc->name)) { + if (cgroup_contains(cg->controllers, cg->n_controllers, cc->name, NULL)) { current_controller = cg; break; } @@ -1021,7 +1024,7 @@ static int prepare_cgns(CgSetEntry *se) for (j = 0; j < n_controllers; j++) { CgControllerEntry *cur = controllers[j]; - if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name)) { + if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name, NULL)) { ctrl = cur; break; } @@ -1093,7 +1096,7 @@ static int move_in_cgroup(CgSetEntry *se, bool setup_cgns) for (j = 0; j < n_controllers; j++) { CgControllerEntry *cur = controllers[j]; - if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name)) { + if (cgroup_contains(cur->cnames, cur->n_cnames, ce->name, NULL)) { ctrl = cur; break; } @@ -1758,7 +1761,7 @@ static int rewrite_cgsets(CgroupEntry *cge, char **controllers, int n_controller * and its path with stripping leading * "/" is matching to be renamed. */ - if (!(cgroup_contains(controllers, n_controllers, cg->name) && + if (!(cgroup_contains(controllers, n_controllers, cg->name, NULL) && strstartswith(cg->path + 1, dir))) continue; @@ -1813,20 +1816,32 @@ static int rewrite_cgroup_roots(CgroupEntry *cge) { int i, j; struct cg_root_opt *o; - char *newroot = NULL; for (i = 0; i < cge->n_controllers; i++) { CgControllerEntry *ctrl = cge->controllers[i]; - newroot = opts.new_global_cg_root; + u64 ctrl_mask = (1ULL << ctrl->n_cnames) - 1; + char *newroot = NULL; list_for_each_entry(o, &opts.new_cgroup_roots, node) { - if (cgroup_contains(ctrl->cnames, ctrl->n_cnames, o->controller)) { - newroot = o->newroot; - break; - } + unsigned old_mask = ctrl_mask; + cgroup_contains(ctrl->cnames, ctrl->n_cnames, + o->controller, &ctrl_mask); + if (old_mask != ctrl_mask) { + if (newroot && strcmp(newroot, o->newroot)) { + pr_err("CG paths mismatch: %s %s\n", + newroot, o->newroot); + return -1; + } + newroot = o->newroot; + } + if (!ctrl_mask) + break; } + if (!newroot) + newroot = opts.new_global_cg_root; + if (newroot) { for (j = 0; j < ctrl->n_dirs; j++) { CgroupDirEntry *cgde = ctrl->dirs[j];