2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 14:25:49 +00:00

cg: add --cgroup-root option

The motivation for this is to be able to restore containers into cgroups other
than what they were dumped in (if, e.g. they might conflict with an existing
container). Suppose you have a container in:

memory:/mycontainer
cpuacct,cpu:/mycontainer
blkio:/mycontainer
name=systemd:/mycontainer

You could then restore them to /mycontainer2 via --cgroup-root /mycontainer2.
If you want to restore different controllers to different paths, you can
provide multiple arguments, for example, passing:

--cgroup-root /mycontainer2 --cgroup-root cpuacct,cpu:/specialcpu \
--cgroup-root name=systemd:/specialsystemd

Would result in things being restored to:

memory:/mycontainer2
cpuacct,cpu:/specialcpu
blkio:/mycontainer2
name=systemd:/specialsystemd

i.e. a --cgroup-root without a controller prefix specifies the new default root
for all cgroups.

Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Tycho Andersen
2014-08-15 17:02:21 -05:00
committed by Pavel Emelyanov
parent 513b0dc3e0
commit 94f6c87c9f
4 changed files with 119 additions and 1 deletions

View File

@@ -1171,6 +1171,77 @@ err:
return -1;
}
static int rewrite_cgsets(CgroupEntry *cge, char **controllers, int n_controllers,
char *from, char *to)
{
int i, j;
for (i = 0; i < cge->n_sets; i++) {
CgSetEntry *set = cge->sets[i];
for (j = 0; j < set->n_ctls; j++) {
CgMemberEntry *cg = set->ctls[j];
if (cgroup_contains(controllers, n_controllers, cg->name) &&
/* +1 to get rid of leading / */
strstartswith(cg->path + 1, from)) {
/* +1 to get rid of leading /, again */
int off = strlen(from) + 1;
/* +1 for trailing NULL */
int newlen = strlen(to) + strlen(cg->path + off) + 1;
char *m = malloc(newlen * sizeof(char*));
if (!m)
return -1;
sprintf(m, "%s%s", to, cg->path + off);
free(cg->path);
cg->path = m;
}
}
}
return 0;
}
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;
list_for_each_entry(o, &opts.new_cgroup_roots, node) {
if (cgroup_contains(ctrl->cnames, ctrl->n_cnames, o->controller)) {
newroot = o->newroot;
break;
}
}
if (newroot) {
for (j = 0; j < ctrl->n_dirs; j++) {
CgroupDirEntry *cgde = ctrl->dirs[j];
char *m;
pr_info("rewriting %s to %s\n", cgde->dir_name, newroot);
if (rewrite_cgsets(cge, ctrl->cnames, ctrl->n_cnames, cgde->dir_name, newroot))
return -1;
m = xstrdup(newroot);
if (!m)
return -1;
free(cgde->dir_name);
cgde->dir_name = m;
}
}
}
return 0;
}
int prepare_cgroup(void)
{
int fd, ret;
@@ -1189,6 +1260,9 @@ int prepare_cgroup(void)
if (ret <= 0) /* Zero is OK -- no sets there. */
return ret;
if (rewrite_cgroup_roots(ce))
return -1;
n_sets = ce->n_sets;
rst_sets = ce->sets;
n_controllers = ce->n_controllers;
@@ -1206,3 +1280,17 @@ int prepare_cgroup(void)
return ret;
}
int new_cg_root_add(char *controller, char *newroot)
{
struct cg_root_opt *o;
o = xmalloc(sizeof(*o));
if (!o)
return -1;
o->controller = controller;
o->newroot = newroot;
list_add(&o->node, &opts.new_cgroup_roots);
return 0;
}