[4/7] mount: rework mount tree build step on restore

Submitted by Pavel Tikhomirov on Feb. 7, 2019, 12:17 p.m.

Details

Message ID 20190207121754.19667-5-ptikhomirov@virtuozzo.com
State New
Series "mount: check mounts after restoring"
Headers show

Commit Message

Pavel Tikhomirov Feb. 7, 2019, 12:17 p.m.
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@virtuozzo.com>
---
 criu/mount.c | 131 +++++++++++++++++++++++++--------------------------
 1 file changed, 65 insertions(+), 66 deletions(-)

Patch hide | download patch | download mbox

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;