Commit 94f6c87c authored by Tycho Andersen's avatar Tycho Andersen Committed by Pavel Emelyanov

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: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 513b0dc3
...@@ -1171,6 +1171,77 @@ err: ...@@ -1171,6 +1171,77 @@ err:
return -1; 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 prepare_cgroup(void)
{ {
int fd, ret; int fd, ret;
...@@ -1189,6 +1260,9 @@ int prepare_cgroup(void) ...@@ -1189,6 +1260,9 @@ int prepare_cgroup(void)
if (ret <= 0) /* Zero is OK -- no sets there. */ if (ret <= 0) /* Zero is OK -- no sets there. */
return ret; return ret;
if (rewrite_cgroup_roots(ce))
return -1;
n_sets = ce->n_sets; n_sets = ce->n_sets;
rst_sets = ce->sets; rst_sets = ce->sets;
n_controllers = ce->n_controllers; n_controllers = ce->n_controllers;
...@@ -1206,3 +1280,17 @@ int prepare_cgroup(void) ...@@ -1206,3 +1280,17 @@ int prepare_cgroup(void)
return ret; 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;
}
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "cr-service.h" #include "cr-service.h"
#include "plugin.h" #include "plugin.h"
#include "mount.h" #include "mount.h"
#include "cgroup.h"
struct cr_options opts; struct cr_options opts;
...@@ -47,6 +48,7 @@ void init_opts(void) ...@@ -47,6 +48,7 @@ void init_opts(void)
INIT_LIST_HEAD(&opts.veth_pairs); INIT_LIST_HEAD(&opts.veth_pairs);
INIT_LIST_HEAD(&opts.scripts); INIT_LIST_HEAD(&opts.scripts);
INIT_LIST_HEAD(&opts.ext_mounts); INIT_LIST_HEAD(&opts.ext_mounts);
INIT_LIST_HEAD(&opts.new_cgroup_roots);
opts.cpu_cap = CPU_CAP_ALL; opts.cpu_cap = CPU_CAP_ALL;
opts.manage_cgroups = false; opts.manage_cgroups = false;
...@@ -169,6 +171,7 @@ int main(int argc, char *argv[]) ...@@ -169,6 +171,7 @@ int main(int argc, char *argv[])
{ "ext-mount-map", required_argument, 0, 'M'}, { "ext-mount-map", required_argument, 0, 'M'},
{ "exec-cmd", no_argument, 0, 59}, { "exec-cmd", no_argument, 0, 59},
{ "manage-cgroups", no_argument, 0, 60}, { "manage-cgroups", no_argument, 0, 60},
{ "cgroup-root", required_argument, 0, 61},
{ }, { },
}; };
...@@ -358,6 +361,21 @@ int main(int argc, char *argv[]) ...@@ -358,6 +361,21 @@ int main(int argc, char *argv[])
case 60: case 60:
opts.manage_cgroups = true; opts.manage_cgroups = true;
break; break;
case 61:
{
char *aux;
aux = strchr(optarg, ':');
if (!aux) {
opts.new_global_cg_root = optarg;
} else {
*aux = '\0';
if (new_cg_root_add(optarg, aux + 1))
return -1;
}
}
break;
case 'M': case 'M':
{ {
char *aux; char *aux;
...@@ -547,6 +565,10 @@ usage: ...@@ -547,6 +565,10 @@ usage:
" -M|--ext-mount-map KEY:VALUE\n" " -M|--ext-mount-map KEY:VALUE\n"
" add external mount mapping\n" " add external mount mapping\n"
" --manage-cgroups dump or restore cgroups the process is in\n" " --manage-cgroups dump or restore cgroups the process is in\n"
" --cgroup-root [controller:]/newroot\n"
" change the root cgroup the controller will be\n"
" installed into. No controller means that root is the\n"
" default for all controllers not specified.\n"
"\n" "\n"
"* Logging:\n" "* Logging:\n"
" -o|--log-file FILE log file name\n" " -o|--log-file FILE log file name\n"
......
...@@ -55,5 +55,5 @@ struct cg_controller *new_controller(const char *name, int heirarchy); ...@@ -55,5 +55,5 @@ struct cg_controller *new_controller(const char *name, int heirarchy);
/* parse all global cgroup information into structures */ /* parse all global cgroup information into structures */
int parse_cg_info(void); int parse_cg_info(void);
int new_cg_root_add(char *controller, char *newroot);
#endif /* __CR_CGROUP_H__ */ #endif /* __CR_CGROUP_H__ */
...@@ -19,6 +19,12 @@ struct script { ...@@ -19,6 +19,12 @@ struct script {
#define CPU_CAP_FPU (1u) #define CPU_CAP_FPU (1u)
#define CPU_CAP_ALL (-1u) #define CPU_CAP_ALL (-1u)
struct cg_root_opt {
struct list_head node;
char *controller;
char *newroot;
};
struct cr_options { struct cr_options {
int final_state; int final_state;
char *show_dump_file; char *show_dump_file;
...@@ -52,6 +58,8 @@ struct cr_options { ...@@ -52,6 +58,8 @@ struct cr_options {
bool force_irmap; bool force_irmap;
char **exec_cmd; char **exec_cmd;
bool manage_cgroups; bool manage_cgroups;
char *new_global_cg_root;
struct list_head new_cgroup_roots;
}; };
extern struct cr_options opts; extern struct cr_options opts;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment