[CRIU] [PATCH 3/3] mnt: Handle external bind mounts according to --ext-mount option (v3)
Pavel Emelyanov
xemul at parallels.com
Mon Jun 9 06:26:59 PDT 2014
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
mount.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++-------
protobuf/mnt.proto | 1 +
2 files changed, 85 insertions(+), 11 deletions(-)
diff --git a/mount.c b/mount.c
index 9cc26ef..4a3c54e 100644
--- a/mount.c
+++ b/mount.c
@@ -63,6 +63,18 @@ int ext_mount_add(char *key, char *val)
return 0;
}
+/* Lookup ext_mount by key field */
+static struct ext_mount *ext_mount_lookup(char *key)
+{
+ struct ext_mount *em;
+
+ list_for_each_entry(em, &opts.ext_mounts, l)
+ if (!strcmp(em->key, key))
+ return em;
+
+ return NULL;
+}
+
/*
* Single linked list of mount points get from proc/images
*/
@@ -342,6 +354,20 @@ static void mnt_tree_show(struct mount_info *tree, int off)
pr_info("%*s<--\n", off, "");
}
+static int try_resolve_ext_mount(struct mount_info *info)
+{
+ struct ext_mount *em;
+
+ em = ext_mount_lookup(info->mountpoint + 1 /* trim the . */);
+ if (em == NULL)
+ return -ENOTSUP;
+
+ pr_info("Found %s mapping for %s mountpoint\n",
+ em->val, info->mountpoint);
+ info->external = em;
+ return 0;
+}
+
static int validate_mounts(struct mount_info *info, bool for_dump)
{
struct mount_info *m, *t;
@@ -403,11 +429,14 @@ static int validate_mounts(struct mount_info *info, bool for_dump)
ret = cr_plugin_dump_ext_mount(m->mountpoint + 1, m->mnt_id);
if (ret == 0)
m->need_plugin = true;
+ else if (ret == -ENOTSUP)
+ ret = try_resolve_ext_mount(m);
} else {
- if (m->need_plugin)
+ if (m->need_plugin || m->external)
/*
* plugin should take care of this one
- * in restore_ext_mount
+ * in restore_ext_mount, or do_bind_mount
+ * will mount it as external
*/
ret = 0;
else
@@ -863,7 +892,6 @@ static int dump_one_mountpoint(struct mount_info *pm, int fd)
me.root_dev = pm->s_dev;
me.parent_mnt_id = pm->parent_mnt_id;
me.flags = pm->flags;
- me.root = pm->root;
me.mountpoint = pm->mountpoint + 1;
me.source = pm->source;
me.options = strip(pm->options);
@@ -876,6 +904,18 @@ static int dump_one_mountpoint(struct mount_info *pm, int fd)
me.with_plugin = true;
}
+ if (pm->external) {
+ /*
+ * For external mount points dump the mapping's
+ * value instead of root. See collect_mnt_from_image
+ * for reverse mapping details.
+ */
+ me.root = pm->external->val;
+ me.has_ext_mount = true;
+ me.ext_mount = true;
+ } else
+ me.root = pm->root;
+
if (pb_write_one(fd, &me, PB_MNT))
return -1;
@@ -1228,9 +1268,20 @@ static int do_bind_mount(struct mount_info *mi)
bool shared = mi->shared_id && mi->shared_id == mi->bind->shared_id;
if (!mi->need_plugin) {
- char rpath[PATH_MAX];
+ char *root, rpath[PATH_MAX];
int tok = 0;
+ if (mi->external) {
+ /*
+ * We have / pointing to criu's ns root still,
+ * so just use the mapping's path. The mountpoint
+ * is tuned in collect_mnt_from_image to refer
+ * to proper location in the namespace we restore.
+ */
+ root = mi->root;
+ goto do_bind;
+ }
+
/*
* Cut common part of root.
* For non-root binds the source is always "/" (checked)
@@ -1245,9 +1296,10 @@ static int do_bind_mount(struct mount_info *mi)
snprintf(rpath, sizeof(rpath), "%s/%s",
mi->bind->mountpoint, mi->root + tok);
- pr_info("\tBind %s to %s\n", rpath, mi->mountpoint);
-
- if (mount(rpath, mi->mountpoint, NULL,
+ root = rpath;
+do_bind:
+ pr_info("\tBind %s to %s\n", root, mi->mountpoint);
+ if (mount(root, mi->mountpoint, NULL,
MS_BIND, NULL) < 0) {
pr_perror("Can't mount at %s", mi->mountpoint);
return -1;
@@ -1547,10 +1599,31 @@ static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
/* FIXME: abort unsupported early */
pm->fstype = decode_fstype(me->fstype);
- pr_debug("\t\tGetting root for %d\n", pm->mnt_id);
- pm->root = xstrdup(me->root);
- if (!pm->root)
- goto err;
+ if (me->ext_mount) {
+ struct ext_mount *em;
+
+ /*
+ * External mount point -- get the reverse mapping
+ * from the command line and put into root's place
+ */
+
+ em = ext_mount_lookup(me->root);
+ if (!em) {
+ pr_err("No mapping for %s mountpoint\n", me->mountpoint);
+ goto err;
+ }
+
+ pm->external = em;
+ pm->root = em->val;
+ pr_debug("Mountpoint %s will have root from %s\n",
+ me->mountpoint, pm->root);
+
+ } else {
+ pr_debug("\t\tGetting root for %d\n", pm->mnt_id);
+ pm->root = xstrdup(me->root);
+ if (!pm->root)
+ goto err;
+ }
len = strlen(me->mountpoint) + root_len + 1;
pm->mountpoint = xmalloc(len);
diff --git a/protobuf/mnt.proto b/protobuf/mnt.proto
index ab85de7..44a6566 100644
--- a/protobuf/mnt.proto
+++ b/protobuf/mnt.proto
@@ -25,4 +25,5 @@ message mnt_entry {
optional uint32 master_id = 11;
optional bool with_plugin = 12;
+ optional bool ext_mount = 13;
}
--
1.8.4.2
More information about the CRIU
mailing list