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:
committed by
Pavel Emelyanov
parent
513b0dc3e0
commit
94f6c87c9f
88
cgroup.c
88
cgroup.c
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user