mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
crtools: Introduce the --ext-mount-map option (v3)
On dump one uses one or more --ext-mount-map option with A:B arguments. A denotes a mountpoint (as seen from the target mount namespace) criu dumps and B is the string that will be written into the image file instead of the mountpoint's root. On restore one uses the same --ext-mount-map option(s) with similar A:B arguments, but this time criu treats A as string from the image's root field (foobar in the example above) and B as the path in criu's mount namespace the should be bind mounted into the mountpoint. v3: * Added documentation * Added RPC bits * Changed option name into --ext-mount-map * Use colon as key and value separator Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
@@ -113,6 +113,17 @@ OPTIONS
|
|||||||
*--veth-pair* 'IN'*=*'OUT'::
|
*--veth-pair* 'IN'*=*'OUT'::
|
||||||
Correspondence between outside and inside names of veth devices.
|
Correspondence between outside and inside names of veth devices.
|
||||||
|
|
||||||
|
*-M*, *--ext-mount-map* 'KEY'*:*'VAL'::
|
||||||
|
Setup mapping for external mounts.
|
||||||
|
|
||||||
|
On dump, KEY is a mountpoint inside container and correspoding VAL
|
||||||
|
is a string that will be written into the image as mountpoint's root
|
||||||
|
value
|
||||||
|
|
||||||
|
On restore KEY is the value from the image (VAL from dump) and the
|
||||||
|
VAL is the path on host that will be bind-mounted into container
|
||||||
|
(to the mountpoint path from image)
|
||||||
|
|
||||||
*--action-script* 'SCRIPT'::
|
*--action-script* 'SCRIPT'::
|
||||||
Add an external action script.
|
Add an external action script.
|
||||||
The environment variable *CRTOOLS_SCRIPT_ACTION* contains one of the
|
The environment variable *CRTOOLS_SCRIPT_ACTION* contains one of the
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "sd-daemon.h"
|
#include "sd-daemon.h"
|
||||||
#include "page-xfer.h"
|
#include "page-xfer.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "mount.h"
|
||||||
|
|
||||||
unsigned int service_sk_ino = -1;
|
unsigned int service_sk_ino = -1;
|
||||||
|
|
||||||
@@ -294,6 +295,11 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < req->n_ext_mnt; i++) {
|
||||||
|
if (ext_mount_add(req->ext_mnt[i]->key, req->ext_mnt[i]->val))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (req->has_cpu_cap)
|
if (req->has_cpu_cap)
|
||||||
opts.cpu_cap = req->cpu_cap;
|
opts.cpu_cap = req->cpu_cap;
|
||||||
|
|
||||||
|
20
crtools.c
20
crtools.c
@@ -34,6 +34,7 @@
|
|||||||
#include "file-lock.h"
|
#include "file-lock.h"
|
||||||
#include "cr-service.h"
|
#include "cr-service.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "mount.h"
|
||||||
|
|
||||||
struct cr_options opts;
|
struct cr_options opts;
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ void init_opts(void)
|
|||||||
opts.final_state = TASK_DEAD;
|
opts.final_state = TASK_DEAD;
|
||||||
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);
|
||||||
|
|
||||||
opts.cpu_cap = CPU_CAP_ALL;
|
opts.cpu_cap = CPU_CAP_ALL;
|
||||||
}
|
}
|
||||||
@@ -124,7 +126,7 @@ int main(int argc, char *argv[])
|
|||||||
int log_level = LOG_UNSET;
|
int log_level = LOG_UNSET;
|
||||||
char *imgs_dir = ".";
|
char *imgs_dir = ".";
|
||||||
char *work_dir = NULL;
|
char *work_dir = NULL;
|
||||||
static const char short_opts[] = "dsRf:F:t:p:hcD:o:n:v::xVr:jlW:L:";
|
static const char short_opts[] = "dsRf:F:t:p:hcD:o:n:v::xVr:jlW:L:M:";
|
||||||
static struct option long_opts[] = {
|
static struct option long_opts[] = {
|
||||||
{ "tree", required_argument, 0, 't' },
|
{ "tree", required_argument, 0, 't' },
|
||||||
{ "pid", required_argument, 0, 'p' },
|
{ "pid", required_argument, 0, 'p' },
|
||||||
@@ -163,6 +165,7 @@ int main(int argc, char *argv[])
|
|||||||
{ "libdir", required_argument, 0, 'L'},
|
{ "libdir", required_argument, 0, 'L'},
|
||||||
{ "cpu-cap", required_argument, 0, 57},
|
{ "cpu-cap", required_argument, 0, 57},
|
||||||
{ "force-irmap", no_argument, 0, 58},
|
{ "force-irmap", no_argument, 0, 58},
|
||||||
|
{ "ext-mount-map", required_argument, 0, 'M'},
|
||||||
{ "exec-cmd", no_argument, 0, 59},
|
{ "exec-cmd", no_argument, 0, 59},
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
@@ -338,6 +341,19 @@ int main(int argc, char *argv[])
|
|||||||
case 59:
|
case 59:
|
||||||
has_exec_cmd = true;
|
has_exec_cmd = true;
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
char *aux;
|
||||||
|
|
||||||
|
aux = strchr(optarg, ':');
|
||||||
|
if (aux == NULL)
|
||||||
|
goto bad_arg;
|
||||||
|
|
||||||
|
*aux = '\0';
|
||||||
|
if (ext_mount_add(optarg, aux + 1))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
pr_msg("Version: %s\n", CRIU_VERSION);
|
pr_msg("Version: %s\n", CRIU_VERSION);
|
||||||
if (strcmp(CRIU_GITID, "0"))
|
if (strcmp(CRIU_GITID, "0"))
|
||||||
@@ -511,6 +527,8 @@ usage:
|
|||||||
" -l|--" OPT_FILE_LOCKS " handle file locks, for safety, only used for container\n"
|
" -l|--" OPT_FILE_LOCKS " handle file locks, for safety, only used for container\n"
|
||||||
" -L|--libdir path to a plugin directory (by default " CR_PLUGIN_DEFAULT ")\n"
|
" -L|--libdir path to a plugin directory (by default " CR_PLUGIN_DEFAULT ")\n"
|
||||||
" --force-irmap force resolving names for inotify/fsnotify watches\n"
|
" --force-irmap force resolving names for inotify/fsnotify watches\n"
|
||||||
|
" -M|--ext-mount-map KEY:VALUE\n"
|
||||||
|
" add external mount mapping\n"
|
||||||
"\n"
|
"\n"
|
||||||
"* Logging:\n"
|
"* Logging:\n"
|
||||||
" -o|--log-file FILE log file name\n"
|
" -o|--log-file FILE log file name\n"
|
||||||
|
@@ -39,6 +39,7 @@ struct cr_options {
|
|||||||
char *pidfile;
|
char *pidfile;
|
||||||
struct list_head veth_pairs;
|
struct list_head veth_pairs;
|
||||||
struct list_head scripts;
|
struct list_head scripts;
|
||||||
|
struct list_head ext_mounts;
|
||||||
char *libdir;
|
char *libdir;
|
||||||
bool use_page_server;
|
bool use_page_server;
|
||||||
unsigned short ps_port;
|
unsigned short ps_port;
|
||||||
|
@@ -35,5 +35,6 @@ extern int restore_task_mnt_ns(struct pstree_item *);
|
|||||||
extern int fini_mnt_ns(void);
|
extern int fini_mnt_ns(void);
|
||||||
|
|
||||||
char *rst_get_mnt_root(int mnt_id);
|
char *rst_get_mnt_root(int mnt_id);
|
||||||
|
int ext_mount_add(char *key, char *val);
|
||||||
|
|
||||||
#endif /* __CR_MOUNT_H__ */
|
#endif /* __CR_MOUNT_H__ */
|
||||||
|
@@ -99,6 +99,7 @@ struct fstype {
|
|||||||
int (*parse)(struct mount_info *pm);
|
int (*parse)(struct mount_info *pm);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ext_mount;
|
||||||
struct mount_info {
|
struct mount_info {
|
||||||
int mnt_id;
|
int mnt_id;
|
||||||
int parent_mnt_id;
|
int parent_mnt_id;
|
||||||
@@ -123,6 +124,8 @@ struct mount_info {
|
|||||||
struct mount_info *next;
|
struct mount_info *next;
|
||||||
struct ns_id *nsid;
|
struct ns_id *nsid;
|
||||||
|
|
||||||
|
struct ext_mount *external;
|
||||||
|
|
||||||
/* tree linkage */
|
/* tree linkage */
|
||||||
struct mount_info *parent;
|
struct mount_info *parent;
|
||||||
struct mount_info *bind;
|
struct mount_info *bind;
|
||||||
|
34
mount.c
34
mount.c
@@ -29,6 +29,40 @@
|
|||||||
|
|
||||||
#include "protobuf/mnt.pb-c.h"
|
#include "protobuf/mnt.pb-c.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure to keep external mount points resolving info.
|
||||||
|
*
|
||||||
|
* On dump the key is the mountpoint as seen from the mount
|
||||||
|
* namespace, the val is some name that will be put into image
|
||||||
|
* instead of the mount point's root path.
|
||||||
|
*
|
||||||
|
* On restore the key is the name from the image (the one
|
||||||
|
* mentioned above) and the val is the path in criu's mount
|
||||||
|
* namespace that will become the mount point's root, i.e. --
|
||||||
|
* be bind mounted to the respective mountpoint.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct ext_mount {
|
||||||
|
char *key;
|
||||||
|
char *val;
|
||||||
|
struct list_head l;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ext_mount_add(char *key, char *val)
|
||||||
|
{
|
||||||
|
struct ext_mount *em;
|
||||||
|
|
||||||
|
em = xmalloc(sizeof(*em));
|
||||||
|
if (!em)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
em->key = key;
|
||||||
|
em->val = val;
|
||||||
|
list_add_tail(&em->l, &opts.ext_mounts);
|
||||||
|
pr_info("Added %s:%s ext mount mapping\n", key, val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Single linked list of mount points get from proc/images
|
* Single linked list of mount points get from proc/images
|
||||||
*/
|
*/
|
||||||
|
@@ -9,6 +9,11 @@ message criu_veth_pair {
|
|||||||
required string if_out = 2;
|
required string if_out = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
message ext_mount_map {
|
||||||
|
required string key = 1;
|
||||||
|
required string val = 2;
|
||||||
|
};
|
||||||
|
|
||||||
message criu_opts {
|
message criu_opts {
|
||||||
required int32 images_dir_fd = 1;
|
required int32 images_dir_fd = 1;
|
||||||
optional int32 pid = 2; /* if not set on dump, will dump requesting process */
|
optional int32 pid = 2; /* if not set on dump, will dump requesting process */
|
||||||
@@ -38,6 +43,8 @@ message criu_opts {
|
|||||||
optional uint32 cpu_cap = 20 [default = 0xffffffff];
|
optional uint32 cpu_cap = 20 [default = 0xffffffff];
|
||||||
optional bool force_irmap = 21;
|
optional bool force_irmap = 21;
|
||||||
repeated string exec_cmd = 22;
|
repeated string exec_cmd = 22;
|
||||||
|
|
||||||
|
repeated ext_mount_map ext_mnt = 23;
|
||||||
}
|
}
|
||||||
|
|
||||||
message criu_dump_resp {
|
message criu_dump_resp {
|
||||||
|
Reference in New Issue
Block a user