[CRIU] [PATCH 4/7] mount: rework mount tree build step on restore
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Thu Feb 7 15:17:51 MSK 2019
Build each mntns mount tree alone just after reading mounts for it from
image. These additional step before merging everything to a single mount
tree allows us to have pointers to each mntns root mount at hand, also
it allows us to remove extra complication from mnt_build_tree.
Teach collect_mnt_from_image return a tail pointer, so we can merge
lists together later after building each tree.
Add separate merge_mount_trees helper to create joint mount tree for all
mntns'es and simplify mnt_build_ids_tree.
I don't see any place where we use mntinfo_tree on restore, so save the
real root of mntns mounts tree in it, instead of root_yard_mp, will need
it in next patches for checking restore of these trees.
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
criu/mount.c | 131 +++++++++++++++++++++++++--------------------------
1 file changed, 65 insertions(+), 66 deletions(-)
diff --git a/criu/mount.c b/criu/mount.c
index 88a30b4fd..3eb36cfdb 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -330,7 +330,7 @@ static bool mounts_equal(struct mount_info *a, struct mount_info *b)
*/
static char *mnt_roots;
-static struct mount_info *mnt_build_ids_tree(struct mount_info *list, struct mount_info *yard_mount)
+static struct mount_info *mnt_build_ids_tree(struct mount_info *list)
{
struct mount_info *m, *root = NULL;
@@ -351,41 +351,14 @@ static struct mount_info *mnt_build_ids_tree(struct mount_info *list, struct mou
if (!parent) {
/* Only a root mount can be without parent */
- if (root == NULL && m->is_ns_root) {
+ if (!root && m->is_ns_root) {
root = m;
- if (!yard_mount)
- continue;
- }
-
- if (!root) {
- pr_err("No parent found for mountpoint %d (@%s)\n",
- m->mnt_id, m->mountpoint);
- return NULL;
- }
-
- pr_debug("Mountpoint %d (@%s) w/o parent %d\n",
- m->mnt_id, m->mountpoint, m->parent_mnt_id);
-
- if (!mounts_sb_equal(root, m) ||
- strcmp(root->root, m->root)) {
- pr_err("Nested mount namespaces with different "
- "roots %d (@%s %s) %d (@%s %s) are not supported yet\n",
- root->mnt_id, root->mountpoint, root->root,
- m->mnt_id, m->mountpoint, m->root);
- return NULL;
- }
-
- /* Mount all namespace roots into the roots yard. */
- parent = yard_mount;
- if (unlikely(!yard_mount)) {
- pr_err("Nested mount %d (@%s %s) w/o root insertion detected\n",
- m->mnt_id, m->mountpoint, m->root);
- return NULL;
+ continue;
}
- pr_debug("Mountpoint %d (@%s) get parent %d (@%s)\n",
- m->mnt_id, m->mountpoint,
- parent->mnt_id, parent->mountpoint);
+ pr_err("No parent found for mountpoint %d (@%s)\n",
+ m->mnt_id, m->mountpoint);
+ return NULL;
}
m->parent = parent;
@@ -397,9 +370,6 @@ static struct mount_info *mnt_build_ids_tree(struct mount_info *list, struct mou
return NULL;
}
- if (yard_mount)
- return yard_mount;
-
return root;
}
@@ -998,8 +968,7 @@ static int resolve_shared_mounts(struct mount_info *info, int root_master_id)
return 0;
}
-static struct mount_info *mnt_build_tree(struct mount_info *list,
- struct mount_info *root_mp)
+static struct mount_info *mnt_build_tree(struct mount_info *list)
{
struct mount_info *tree;
@@ -1008,7 +977,7 @@ static struct mount_info *mnt_build_tree(struct mount_info *list,
*/
pr_info("Building mountpoints tree\n");
- tree = mnt_build_ids_tree(list, root_mp);
+ tree = mnt_build_ids_tree(list);
if (!tree)
return NULL;
@@ -1691,7 +1660,7 @@ struct mount_info *collect_mntinfo(struct ns_id *ns, bool for_dump)
return NULL;
}
- ns->mnt.mntinfo_tree = mnt_build_tree(pm, NULL);
+ ns->mnt.mntinfo_tree = mnt_build_tree(pm);
if (ns->mnt.mntinfo_tree == NULL)
goto err;
@@ -2882,7 +2851,7 @@ static int get_mp_mountpoint(char *mountpoint, struct mount_info *mi, char *root
return 0;
}
-static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
+static int collect_mnt_from_image(struct mount_info **head, struct mount_info **tail, struct ns_id *nsid)
{
MntEntry *me = NULL;
int ret, root_len = 1;
@@ -2910,8 +2879,10 @@ static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
goto err;
pm->nsid = nsid;
- pm->next = *pms;
- *pms = pm;
+ pm->next = *head;
+ *head = pm;
+ if (!*tail)
+ *tail = pm;
pm->mnt_id = me->mnt_id;
pm->parent_mnt_id = me->parent_mnt_id;
@@ -2996,11 +2967,20 @@ int read_mnt_ns_img(void)
}
for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
+ struct mount_info *head = NULL, *tail = NULL;
+
if (nsid->nd != &mnt_ns_desc)
continue;
- if (collect_mnt_from_image(&pms, nsid))
+ if (collect_mnt_from_image(&head, &tail, nsid))
+ return -1;
+
+ nsid->mnt.mntinfo_tree = mnt_build_tree(head);
+ if (!nsid->mnt.mntinfo_tree)
return -1;
+
+ tail->next = pms;
+ pms = head;
}
mntinfo = pms;
@@ -3102,6 +3082,40 @@ void fini_restore_mntns(void)
}
}
+static int merge_mount_trees(struct mount_info *root_yard)
+{
+ struct mount_info *first = NULL;
+ struct ns_id *nsid;
+
+ /* Merge mount trees together under root_yard */
+ for (nsid = ns_ids; nsid; nsid = nsid->next) {
+ struct mount_info *root;
+
+ if (nsid->nd != &mnt_ns_desc)
+ continue;
+
+ root = nsid->mnt.mntinfo_tree;
+
+ if (!first)
+ first = root;
+ else if (!mounts_sb_equal(root, first) ||
+ strcmp(root->root, first->root)) {
+ pr_err("Nested mount namespaces with different "
+ "roots %d (@%s %s) %d (@%s %s) are not supported yet\n",
+ root->mnt_id, root->mountpoint, root->root,
+ first->mnt_id, first->mountpoint, first->root);
+ return -1;
+ }
+
+ pr_debug("Mountpoint %d (@%s) moved to the root yard\n",
+ root->mnt_id, root->mountpoint);
+ root->parent = root_yard;
+ list_add_tail(&root->siblings, &root_yard->children);
+ }
+
+ return 0;
+}
+
/*
* All nested mount namespaces are restore as sub-trees of the root namespace.
*/
@@ -3141,8 +3155,6 @@ static int populate_roots_yard(void)
static int populate_mnt_ns(void)
{
- struct mount_info *pms;
- struct ns_id *nsid;
int ret;
root_yard_mp = mnt_entry_alloc();
@@ -3152,40 +3164,27 @@ static int populate_mnt_ns(void)
root_yard_mp->mountpoint = mnt_roots;
root_yard_mp->mounted = true;
- pms = mnt_build_tree(mntinfo, root_yard_mp);
- if (!pms)
+ if (merge_mount_trees(root_yard_mp))
return -1;
#ifdef CONFIG_BINFMT_MISC_VIRTUALIZED
if (!opts.has_binfmt_misc && !list_empty(&binfmt_misc_list)) {
/* Add to mount tree. Generic code will mount it later */
- ret = add_cr_time_mount(pms, "binfmt_misc", BINFMT_MISC_HOME, 0);
+ ret = add_cr_time_mount(root_yard_mp, "binfmt_misc", BINFMT_MISC_HOME, 0);
if (ret)
return -1;
}
#endif
- if (resolve_shared_mounts(mntinfo, pms->master_id))
+ if (resolve_shared_mounts(mntinfo, 0))
return -1;
- for (nsid = ns_ids; nsid; nsid = nsid->next) {
- if (nsid->nd != &mnt_ns_desc)
- continue;
-
- /*
- * Make trees of all namespaces look the
- * same, so that manual paths resolution
- * works on them.
- */
- nsid->mnt.mntinfo_tree = pms;
- }
-
if (validate_mounts(mntinfo, false))
return -1;
- mnt_tree_for_each(pms, set_is_overmounted);
+ mnt_tree_for_each(root_yard_mp, set_is_overmounted);
- if (find_remap_mounts(pms))
+ if (find_remap_mounts(root_yard_mp))
return -1;
if (populate_roots_yard())
@@ -3194,8 +3193,8 @@ static int populate_mnt_ns(void)
if (mount_clean_path())
return -1;
- ret = mnt_tree_for_each(pms, do_mount_one);
- mnt_tree_for_each(pms, do_close_one);
+ ret = mnt_tree_for_each(root_yard_mp, do_mount_one);
+ mnt_tree_for_each(root_yard_mp, do_close_one);
if (ret == 0 && fixup_remap_mounts())
return -1;
--
2.20.1
More information about the CRIU
mailing list