[CRIU] [PATCH 3/4] mount: fix restoring a bind-mount when its root is overmounted

Andrey Vagin avagin at openvz.org
Fri Dec 4 03:38:04 PST 2015


From: Andrew Vagin <avagin at virtuozzo.com>

In this case we mount source mount in a temporary place and use it to
create the bind-mount.

Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 mount.c | 49 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 12 deletions(-)

diff --git a/mount.c b/mount.c
index bd5a7b9..842b5d4 100644
--- a/mount.c
+++ b/mount.c
@@ -2023,11 +2023,16 @@ static int restore_ext_mount(struct mount_info *mi)
 
 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];
 	bool force_private_remount = false;
 	unsigned long mflags;
+	int exit_code = -1;
 	bool shared = 0;
+	char *mnt_path;
 	struct stat st;
+	bool umount_mnt_path = false;
 
 	if (mi->need_plugin) {
 		if (restore_ext_mount(mi))
@@ -2050,8 +2055,17 @@ static int do_bind_mount(struct mount_info *mi)
 	shared = mi->shared_id && mi->shared_id == mi->bind->shared_id;
 	cut_root = cut_root_for_bind(mi->root, mi->bind->root);
 
-	snprintf(rpath, sizeof(rpath), "%s/%s",
-			mi->bind->mountpoint, cut_root);
+	if (list_empty(&mi->bind->children))
+		mnt_path = mi->bind->mountpoint;
+	else {
+		mnt_path = get_clean_mnt(mi->bind, mnt_path_tmp, mnt_path_root);
+		umount_mnt_path = true;
+	}
+	if (mnt_path == NULL)
+		return -1;
+
+	snprintf(rpath, sizeof(rpath), "%s/%s/.",
+			mnt_path, cut_root);
 	root = rpath;
 do_bind:
 	pr_info("\tBind %s to %s\n", root, mi->mountpoint);
@@ -2059,51 +2073,51 @@ do_bind:
 	if (unlikely(mi->deleted)) {
 		if (stat(mi->mountpoint, &st)) {
 			pr_perror("Can't fetch stat on %s", mi->mountpoint);
-			return -1;
+			goto err;
 		}
 
 		if (S_ISDIR(st.st_mode)) {
 			if (mkdir(root, (st.st_mode & ~S_IFMT))) {
 				pr_perror("Can't re-create deleted directory %s", root);
-				return -1;
+				goto err;
 			}
 		} else if (S_ISREG(st.st_mode)) {
 			int fd = open(root, O_WRONLY | O_CREAT | O_EXCL,
 				      st.st_mode & ~S_IFMT);
 			if (fd < 0) {
 				pr_perror("Can't re-create deleted file %s", root);
-				return -1;
+				goto err;
 			}
 			close(fd);
 		} else {
 			pr_err("Unsupported st_mode 0%o deleted root %s\n",
 			       (int)st.st_mode, root);
-			return -1;
+			goto err;
 		}
 	}
 
 	if (mount(root, mi->mountpoint, NULL, MS_BIND, NULL) < 0) {
 		pr_perror("Can't mount at %s", mi->mountpoint);
-		return -1;
+		goto err;
 	}
 
 	mflags = mi->flags & (~MS_PROPAGATE);
 	if (!mi->bind || mflags != (mi->bind->flags & (~MS_PROPAGATE)))
 		if (mount(NULL, mi->mountpoint, NULL, MS_BIND | MS_REMOUNT | mflags, NULL)) {
 			pr_perror("Can't mount at %s", mi->mountpoint);
-			return -1;
+			goto err;
 		}
 
 	if (unlikely(mi->deleted)) {
 		if (S_ISDIR(st.st_mode)) {
 			if (rmdir(root)) {
 				pr_perror("Can't remove deleted directory %s", root);
-				return -1;
+				goto err;
 			}
 		} else if (S_ISREG(st.st_mode)) {
 			if (unlink(root)) {
 				pr_perror("Can't unlink deleted file %s", root);
-				return -1;
+				goto err;
 			}
 		}
 	}
@@ -2118,8 +2132,19 @@ out:
 		return -1;
 
 	mi->mounted = true;
-
-	return 0;
+	exit_code = 0;
+err:
+	if (umount_mnt_path) {
+		if (umount(mnt_path)) {
+			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;
 }
 
 static bool can_mount_now(struct mount_info *mi)
-- 
2.4.3



More information about the CRIU mailing list