From c7e0042946c9a402dff8d8a75b29ffc9c375ea26 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 9 Jun 2014 17:26:17 +0400 Subject: [PATCH] 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 --- Documentation/criu.txt | 11 +++++++++++ cr-service.c | 6 ++++++ crtools.c | 20 +++++++++++++++++++- include/cr_options.h | 1 + include/mount.h | 1 + include/proc_parse.h | 3 +++ mount.c | 34 ++++++++++++++++++++++++++++++++++ protobuf/rpc.proto | 7 +++++++ 8 files changed, 82 insertions(+), 1 deletion(-) diff --git a/Documentation/criu.txt b/Documentation/criu.txt index 9c9a9c995..474011c5a 100644 --- a/Documentation/criu.txt +++ b/Documentation/criu.txt @@ -113,6 +113,17 @@ OPTIONS *--veth-pair* 'IN'*=*'OUT':: 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':: Add an external action script. The environment variable *CRTOOLS_SCRIPT_ACTION* contains one of the diff --git a/cr-service.c b/cr-service.c index d14769255..dc0ff5a1e 100644 --- a/cr-service.c +++ b/cr-service.c @@ -23,6 +23,7 @@ #include "sd-daemon.h" #include "page-xfer.h" #include "net.h" +#include "mount.h" unsigned int service_sk_ino = -1; @@ -294,6 +295,11 @@ static int setup_opts_from_req(int sk, CriuOpts *req) 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) opts.cpu_cap = req->cpu_cap; diff --git a/crtools.c b/crtools.c index 38b4b0db2..568418657 100644 --- a/crtools.c +++ b/crtools.c @@ -34,6 +34,7 @@ #include "file-lock.h" #include "cr-service.h" #include "plugin.h" +#include "mount.h" struct cr_options opts; @@ -45,6 +46,7 @@ void init_opts(void) opts.final_state = TASK_DEAD; INIT_LIST_HEAD(&opts.veth_pairs); INIT_LIST_HEAD(&opts.scripts); + INIT_LIST_HEAD(&opts.ext_mounts); opts.cpu_cap = CPU_CAP_ALL; } @@ -124,7 +126,7 @@ int main(int argc, char *argv[]) int log_level = LOG_UNSET; char *imgs_dir = "."; 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[] = { { "tree", required_argument, 0, 't' }, { "pid", required_argument, 0, 'p' }, @@ -163,6 +165,7 @@ int main(int argc, char *argv[]) { "libdir", required_argument, 0, 'L'}, { "cpu-cap", required_argument, 0, 57}, { "force-irmap", no_argument, 0, 58}, + { "ext-mount-map", required_argument, 0, 'M'}, { "exec-cmd", no_argument, 0, 59}, { }, }; @@ -338,6 +341,19 @@ int main(int argc, char *argv[]) case 59: has_exec_cmd = true; 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': pr_msg("Version: %s\n", CRIU_VERSION); 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|--libdir path to a plugin directory (by default " CR_PLUGIN_DEFAULT ")\n" " --force-irmap force resolving names for inotify/fsnotify watches\n" +" -M|--ext-mount-map KEY:VALUE\n" +" add external mount mapping\n" "\n" "* Logging:\n" " -o|--log-file FILE log file name\n" diff --git a/include/cr_options.h b/include/cr_options.h index f2106b0c0..2732e58d6 100644 --- a/include/cr_options.h +++ b/include/cr_options.h @@ -39,6 +39,7 @@ struct cr_options { char *pidfile; struct list_head veth_pairs; struct list_head scripts; + struct list_head ext_mounts; char *libdir; bool use_page_server; unsigned short ps_port; diff --git a/include/mount.h b/include/mount.h index 82e844023..670e77905 100644 --- a/include/mount.h +++ b/include/mount.h @@ -35,5 +35,6 @@ extern int restore_task_mnt_ns(struct pstree_item *); extern int fini_mnt_ns(void); char *rst_get_mnt_root(int mnt_id); +int ext_mount_add(char *key, char *val); #endif /* __CR_MOUNT_H__ */ diff --git a/include/proc_parse.h b/include/proc_parse.h index 09c9efdd9..cca532232 100644 --- a/include/proc_parse.h +++ b/include/proc_parse.h @@ -99,6 +99,7 @@ struct fstype { int (*parse)(struct mount_info *pm); }; +struct ext_mount; struct mount_info { int mnt_id; int parent_mnt_id; @@ -123,6 +124,8 @@ struct mount_info { struct mount_info *next; struct ns_id *nsid; + struct ext_mount *external; + /* tree linkage */ struct mount_info *parent; struct mount_info *bind; diff --git a/mount.c b/mount.c index 577a991f0..f7ec623c2 100644 --- a/mount.c +++ b/mount.c @@ -29,6 +29,40 @@ #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 */ diff --git a/protobuf/rpc.proto b/protobuf/rpc.proto index b26186a6b..e50d97cb1 100644 --- a/protobuf/rpc.proto +++ b/protobuf/rpc.proto @@ -9,6 +9,11 @@ message criu_veth_pair { required string if_out = 2; }; +message ext_mount_map { + required string key = 1; + required string val = 2; +}; + message criu_opts { required int32 images_dir_fd = 1; 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 bool force_irmap = 21; repeated string exec_cmd = 22; + + repeated ext_mount_map ext_mnt = 23; } message criu_dump_resp {