[CRIU] [PATCH] mount: Umount nested temporary mount pathes in do_bind_mount()

Kirill Tkhai ktkhai at virtuozzo.com
Thu Feb 25 05:54:27 PST 2016


When a parent directory of restored mount is bound to itself,
a temporary mount is cloned, so we need to umount it twice:

# mkdir -p parent/child /tmp/cr-XXX
# mount --bind parent parent
# mount --bind parent/child /tmp/cr-XXX/
# mount --bind /tmp/cr-XXX/ parent/child
# umount /tmp/cr-XXX/
# mount | grep "/tmp/cr-XXX"
/dev/sda3 on /tmp/cr-XXX type ext4 (rw,noatime,nodiratime,data=ordered)

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 criu/mount.c |   27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/criu/mount.c b/criu/mount.c
index 1a6b034..bce2465 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -301,6 +301,26 @@ static bool mounts_equal(struct mount_info *a, struct mount_info *b)
 }
 
 /*
+ * Successively umount all file systems mounted on @path
+ */
+static int umount2_nested(const char *path, int flags)
+{
+	bool once = true;
+	int ret;
+
+	while (1) {
+		ret = umount2(path, flags);
+		if (ret)
+			break;
+		once = false;
+	}
+
+	if (once || errno != EINVAL)
+		return -1;
+	return 0;
+}
+
+/*
  * mnt_roots is a temporary directory for restoring sub-trees of
  * non-root namespaces.
  */
@@ -2397,7 +2417,12 @@ static int do_bind_mount(struct mount_info *mi)
 			pr_perror("Unable to make %s private", mnt_path);
 			return -1;
 		}
-		if (umount2(mnt_path, MNT_DETACH)) {
+		/*
+		 * If mi and mi->bind have the same mountpoint, and
+		 * a parent dir of the mountpoint is bound to itself,
+		 * then we have several mounts on mnt_path.
+		 */
+		if (umount2_nested(mnt_path, MNT_DETACH)) {
 			pr_perror("Unable to umount %s", mnt_path);
 			return -1;
 		}



More information about the CRIU mailing list