mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
Add new command line option: --cgroup-yard
Instead of creating cgroup yard in CRIU, now we can create it externally and pass it to CRIU. Useful if somebody doesn't want to grant CAP_SYS_ADMIN to CRIU. Signed-off-by: Michał Cłapiński <mclapinski@google.com>
This commit is contained in:
committed by
Andrei Vagin
parent
ad7e82a30f
commit
2f337652ad
@@ -266,10 +266,33 @@ For example, the command line for the above example should look like this:
|
||||
discovered automatically (usually via */proc*). This option is
|
||||
useful when one needs *criu* to skip some controllers.
|
||||
|
||||
*--cgroup-props-ignore-default*::
|
||||
When combined with *--cgroup-props*, makes *criu* substitute
|
||||
a predefined controller property with the new one shipped. If the option
|
||||
is not used, the predefined properties are merged with the provided ones.
|
||||
*--cgroup-yard* 'path'::
|
||||
Instead of trying to mount cgroups in CRIU, provide a path to a directory
|
||||
with already created cgroup yard. Useful if you don't want to grant
|
||||
CAP_SYS_ADMIN to CRIU. For every cgroup mount there should be exactly one
|
||||
directory. If there is only one controller in this mount, the dir's name
|
||||
should be just the name of the controller. If there are multiple controllers
|
||||
comounted, the directory name should have them be separated by a comma.
|
||||
+
|
||||
For example, if */proc/cgroups* looks like this:
|
||||
+
|
||||
----------
|
||||
#subsys_name hierarchy num_cgroups enabled
|
||||
cpu 1 1 1
|
||||
devices 2 2 1
|
||||
freezer 2 2 1
|
||||
----------
|
||||
+
|
||||
then you can create the cgroup yard by the following commands:
|
||||
+
|
||||
----------
|
||||
mkdir private_yard
|
||||
cd private_yard
|
||||
mkdir cpu
|
||||
mount -t cgroup -o cpu none cpu
|
||||
mkdir devices,freezer
|
||||
mount -t cgroup -o devices,freezer none devices,freezer
|
||||
----------
|
||||
|
||||
*--tcp-established*::
|
||||
Checkpoint established TCP connections.
|
||||
@@ -442,6 +465,11 @@ The 'mode' may be one of the following:
|
||||
|
||||
*ignore*::: Don't deal with cgroups and pretend that they don't exist.
|
||||
|
||||
*--cgroup-yard* 'path'::
|
||||
Instead of trying to mount cgroups in CRIU, provide a path to a directory
|
||||
with already created cgroup yard. For more information look in the *dump*
|
||||
section.
|
||||
|
||||
*--cgroup-root* ['controller'*:*]/'newroot'::
|
||||
Change the root cgroup the controller will be installed into. No controller
|
||||
means that root is the default for all controllers not specified.
|
||||
|
101
criu/cgroup.c
101
criu/cgroup.c
@@ -549,8 +549,9 @@ static int collect_cgroups(struct list_head *ctls)
|
||||
int fd = -1;
|
||||
|
||||
list_for_each_entry(cc, ctls, l) {
|
||||
char path[PATH_MAX], mopts[1024], *root;
|
||||
char path[PATH_MAX], *root;
|
||||
char prefix[] = ".criu.cgmounts.XXXXXX";
|
||||
const char namestr[] = "name=";
|
||||
struct cg_controller *cg;
|
||||
struct cg_root_opt *o;
|
||||
|
||||
@@ -568,7 +569,7 @@ static int collect_cgroups(struct list_head *ctls)
|
||||
|
||||
if (!current_controller) {
|
||||
/* only allow "fake" controllers to be created this way */
|
||||
if (!strstartswith(cc->name, "name=")) {
|
||||
if (!strstartswith(cc->name, namestr)) {
|
||||
pr_err("controller %s not found\n", cc->name);
|
||||
return -1;
|
||||
} else {
|
||||
@@ -586,26 +587,45 @@ static int collect_cgroups(struct list_head *ctls)
|
||||
if (!opts.manage_cgroups)
|
||||
continue;
|
||||
|
||||
if (strstartswith(cc->name, "name="))
|
||||
snprintf(mopts, sizeof(mopts), "none,%s", cc->name);
|
||||
else
|
||||
snprintf(mopts, sizeof(mopts), "%s", cc->name);
|
||||
if (opts.cgroup_yard) {
|
||||
char dir_path[PATH_MAX];
|
||||
int off;
|
||||
|
||||
off = snprintf(dir_path, PATH_MAX, "%s/", opts.cgroup_yard);
|
||||
if (strstartswith(cc->name, namestr))
|
||||
snprintf(dir_path + off, PATH_MAX, "%s", cc->name + strlen(namestr));
|
||||
else
|
||||
snprintf(dir_path + off, PATH_MAX, "%s", cc->name);
|
||||
|
||||
if (mkdtemp(prefix) == NULL) {
|
||||
pr_perror("can't make dir for cg mounts");
|
||||
return -1;
|
||||
fd = open(dir_path, O_RDONLY | O_DIRECTORY, 0);
|
||||
if (fd < 0) {
|
||||
pr_perror("couldn't open %s", dir_path);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
char mopts[1024];
|
||||
|
||||
if (strstartswith(cc->name, namestr))
|
||||
snprintf(mopts, sizeof(mopts), "none,%s", cc->name);
|
||||
else
|
||||
snprintf(mopts, sizeof(mopts), "%s", cc->name);
|
||||
|
||||
if (mkdtemp(prefix) == NULL) {
|
||||
pr_perror("can't make dir for cg mounts");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("none", prefix, "cgroup", 0, mopts) < 0) {
|
||||
pr_perror("couldn't mount %s", mopts);
|
||||
rmdir(prefix);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open_detach_mount(prefix);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("none", prefix, "cgroup", 0, mopts) < 0) {
|
||||
pr_perror("couldn't mount %s", 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);
|
||||
|
||||
root = cc->path;
|
||||
@@ -620,6 +640,7 @@ static int collect_cgroups(struct list_head *ctls)
|
||||
snprintf(path + path_pref_len, PATH_MAX - path_pref_len, "%s", root);
|
||||
|
||||
ret = ftw(path, add_cgroup, 4);
|
||||
|
||||
if (ret < 0)
|
||||
pr_perror("failed walking %s for empty cgroups", path);
|
||||
|
||||
@@ -1167,10 +1188,12 @@ void fini_cgroup(void)
|
||||
return;
|
||||
|
||||
close_service_fd(CGROUP_YARD);
|
||||
if (umount2(cg_yard, MNT_DETACH))
|
||||
pr_perror("Unable to umount %s", cg_yard);
|
||||
if (rmdir(cg_yard))
|
||||
pr_perror("Unable to remove %s", cg_yard);
|
||||
if (!opts.cgroup_yard) {
|
||||
if (umount2(cg_yard, MNT_DETACH))
|
||||
pr_perror("Unable to umount %s", cg_yard);
|
||||
if (rmdir(cg_yard))
|
||||
pr_perror("Unable to remove %s", cg_yard);
|
||||
}
|
||||
xfree(cg_yard);
|
||||
cg_yard = NULL;
|
||||
}
|
||||
@@ -1652,20 +1675,28 @@ static int prepare_cgroup_sfd(CgroupEntry *ce)
|
||||
pr_info("Preparing cgroups yard (cgroups restore mode %#x)\n",
|
||||
opts.manage_cgroups);
|
||||
|
||||
off = sprintf(paux, ".criu.cgyard.XXXXXX");
|
||||
if (mkdtemp(paux) == NULL) {
|
||||
pr_perror("Can't make temp cgyard dir");
|
||||
return -1;
|
||||
}
|
||||
if (opts.cgroup_yard) {
|
||||
off = sprintf(paux, "%s", opts.cgroup_yard);
|
||||
|
||||
cg_yard = xstrdup(paux);
|
||||
if (!cg_yard) {
|
||||
rmdir(paux);
|
||||
return -1;
|
||||
}
|
||||
cg_yard = xstrdup(paux);
|
||||
if (!cg_yard)
|
||||
return -1;
|
||||
} else {
|
||||
off = sprintf(paux, ".criu.cgyard.XXXXXX");
|
||||
if (mkdtemp(paux) == NULL) {
|
||||
pr_perror("Can't make temp cgyard dir");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (make_yard(cg_yard))
|
||||
goto err;
|
||||
cg_yard = xstrdup(paux);
|
||||
if (!cg_yard) {
|
||||
rmdir(paux);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (make_yard(cg_yard))
|
||||
goto err;
|
||||
}
|
||||
|
||||
pr_debug("Opening %s as cg yard\n", cg_yard);
|
||||
i = open(cg_yard, O_DIRECTORY);
|
||||
|
@@ -516,6 +516,7 @@ int parse_options(int argc, char **argv, bool *usage_error,
|
||||
{ "tls-key", required_argument, 0, 1095},
|
||||
BOOL_OPT("tls", &opts.tls),
|
||||
{"tls-no-cn-verify", no_argument, &opts.tls_no_cn_verify, true},
|
||||
{ "cgroup-yard", required_argument, 0, 1096 },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -814,6 +815,9 @@ int parse_options(int argc, char **argv, bool *usage_error,
|
||||
case 1095:
|
||||
SET_CHAR_OPTS(tls_key, optarg);
|
||||
break;
|
||||
case 1096:
|
||||
SET_CHAR_OPTS(cgroup_yard, optarg);
|
||||
break;
|
||||
case 'V':
|
||||
pr_msg("Version: %s\n", CRIU_VERSION);
|
||||
if (strcmp(CRIU_GITID, "0"))
|
||||
|
@@ -608,6 +608,9 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (req->cgroup_yard)
|
||||
SET_CHAR_OPTS(cgroup_yard, req->cgroup_yard);
|
||||
|
||||
if (req->tls_cacert)
|
||||
SET_CHAR_OPTS(tls_cacert, req->tls_cacert);
|
||||
if (req->tls_cacrl)
|
||||
|
@@ -366,6 +366,10 @@ usage:
|
||||
" --cgroup-dump-controller NAME\n"
|
||||
" define cgroup controller to be dumped\n"
|
||||
" and skip anything else present in system\n"
|
||||
" --cgroup-yard PATH\n"
|
||||
" instead of trying to mount cgroups in CRIU, provide\n"
|
||||
" a path to a directory with already created cgroup yard.\n"
|
||||
" Useful if you don't want to grant CAP_SYS_ADMIN to CRIU\n"
|
||||
" --lsm-profile TYPE:NAME\n"
|
||||
" Specify an LSM profile to be used during restore.\n"
|
||||
" The type can be either 'apparmor' or 'selinux'.\n"
|
||||
|
@@ -190,7 +190,7 @@ int prepare_inventory(InventoryEntry *he)
|
||||
struct dmp_info d;
|
||||
} crt = { .i.pid = &pid };
|
||||
|
||||
pr_info("Perparing image inventory (version %u)\n", CRTOOLS_IMAGES_V1);
|
||||
pr_info("Preparing image inventory (version %u)\n", CRTOOLS_IMAGES_V1);
|
||||
|
||||
he->img_version = CRTOOLS_IMAGES_V1_1;
|
||||
he->fdinfo_per_id = true;
|
||||
|
@@ -106,6 +106,7 @@ struct cr_options {
|
||||
char *cgroup_props;
|
||||
char *cgroup_props_file;
|
||||
struct list_head new_cgroup_roots;
|
||||
char *cgroup_yard;
|
||||
bool autodetect_ext_mounts;
|
||||
int enable_external_sharing;
|
||||
int enable_external_masters;
|
||||
|
@@ -120,6 +120,7 @@ message criu_opts {
|
||||
optional string tls_key = 57;
|
||||
optional bool tls = 58;
|
||||
optional bool tls_no_cn_verify = 59;
|
||||
optional string cgroup_yard = 60;
|
||||
/* optional bool check_mounts = 128; */
|
||||
}
|
||||
|
||||
|
13
lib/c/criu.c
13
lib/c/criu.c
@@ -987,6 +987,19 @@ int criu_local_add_cg_dump_controller(criu_opts *opts, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int criu_local_add_cg_yard(criu_opts *opts, const char *path)
|
||||
{
|
||||
char *new;
|
||||
|
||||
new = strdup(path);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
|
||||
free(opts->rpc->cgroup_yard);
|
||||
opts->rpc->cgroup_yard = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int criu_add_skip_mnt(const char *mnt)
|
||||
{
|
||||
return criu_local_add_skip_mnt(global_opts, mnt);
|
||||
|
@@ -207,6 +207,7 @@ int criu_local_add_irmap_path(criu_opts *opts, const char *path);
|
||||
int criu_local_add_cg_props(criu_opts *opts, const char *stream);
|
||||
int criu_local_add_cg_props_file(criu_opts *opts, const char *path);
|
||||
int criu_local_add_cg_dump_controller(criu_opts *opts, const char *name);
|
||||
int criu_local_add_cg_yard(criu_opts *opts, const char *path);
|
||||
int criu_local_add_inherit_fd(criu_opts *opts, int fd, const char *key);
|
||||
int criu_local_add_external(criu_opts *opts, const char *key);
|
||||
int criu_local_set_page_server_address_port(criu_opts *opts, const char *address, int port);
|
||||
|
Reference in New Issue
Block a user