[CRIU] [PATCH 4/4] mount: don't use a shared mount to get a clean mount

Andrey Vagin avagin at openvz.org
Wed Mar 2 23:00:15 PST 2016


From: Andrew Vagin <avagin at virtuozzo.com>

When we bind-mount something into a shared mount,
a new mount will be shared too.

By default /tmp is a shared mount, so when we get a "clean mount",
it will be always shared. On restore we don't need this side effect,
so let's do bind-mount in a private mount.

Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 criu/mount.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 57 insertions(+), 8 deletions(-)

diff --git a/criu/mount.c b/criu/mount.c
index 20a95d1..bac42e1 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -2279,10 +2279,51 @@ static int restore_ext_mount(struct mount_info *mi)
 	return ret;
 }
 
+static char mnt_clean_path[] = "/tmp/cr-tmpfs.XXXXXX";
+
+static int mount_clean_path()
+{
+	/*
+	 * To make a bind mount, we need to have access to a source directory,
+	 * which can be over-mounted. The idea is to mount a source mount in
+	 * an intermediate place without MS_REC and then create a target mounts.
+	 * This intermediate place should be a private mount to not affect
+	 * properties of the source mount.
+	 */
+	if (mkdtemp(mnt_clean_path) == NULL) {
+		pr_perror("Unable to create a temporary directory");
+		return -1;
+	}
+
+	if (mount(mnt_clean_path, mnt_clean_path, NULL, MS_BIND, NULL)) {
+		pr_perror("Unable to mount tmpfs into %s", mnt_clean_path);
+		return -1;
+	}
+
+	if (mount(NULL, mnt_clean_path, NULL, MS_PRIVATE, NULL)) {
+		pr_perror("Unable to mark %s as private", mnt_clean_path);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int umount_clean_path()
+{
+	if (umount2(mnt_clean_path, MNT_DETACH)) {
+		pr_perror("Unable to umount %s\n", mnt_clean_path);
+		return -1;
+	}
+
+	if (rmdir(mnt_clean_path)) {
+		pr_perror("Unable to remove %s", mnt_clean_path);
+	}
+
+	return 0;
+}
+
 static int do_bind_mount(struct mount_info *mi)
 {
-	char mnt_path_tmp[] = "/tmp/cr-tmpfs.XXXXXX";
-	char mnt_path_root[] = "/cr-tmpfs.XXXXXX";
 	char *root, *cut_root, rpath[PATH_MAX];
 	unsigned long mflags;
 	int exit_code = -1;
@@ -2321,7 +2362,11 @@ static int do_bind_mount(struct mount_info *mi)
 		mnt_path = mi->bind->mountpoint;
 	else {
 		/* mi->bind->mountpoint may be overmounted */
-		mnt_path = get_clean_mnt(mi->bind, mnt_path_tmp, mnt_path_root);
+		if (mount(mi->bind->mountpoint, mnt_clean_path, NULL, MS_BIND, NULL)) {
+			pr_perror("Unable to bind-mount %s to %s",
+					mi->bind->mountpoint, mnt_clean_path);
+		}
+		mnt_path = mnt_clean_path;
 		umount_mnt_path = true;
 	}
 	if (mnt_path == NULL)
@@ -2410,10 +2455,6 @@ err:
 			pr_perror("Unable to umount %s", mnt_path);
 			return -1;
 		}
-		if (rmdir(mnt_path)) {
-			pr_perror("Unable to remove %s", mnt_path);
-			return -1;
-		}
 	}
 	return exit_code;
 }
@@ -3025,6 +3066,7 @@ static int populate_mnt_ns(void)
 	struct mount_info *pms;
 	struct ns_id *nsid;
 	struct mount_info *roots_mp = NULL;
+	int ret;
 
 	if (mnt_roots) {
 		/* mnt_roots is a tmpfs mount and it's private */
@@ -3069,7 +3111,14 @@ static int populate_mnt_ns(void)
 	if (populate_roots_yard())
 		return -1;
 
-	return mnt_tree_for_each(pms, do_mount_one);
+	if (mount_clean_path())
+		return -1;
+
+	ret = mnt_tree_for_each(pms, do_mount_one);
+
+	if (umount_clean_path())
+		return -1;
+	return ret;
 }
 
 int depopulate_roots_yard(void)
-- 
2.5.0



More information about the CRIU mailing list