72332c
From 27034e7c64b00a1f2467afb5ebb1d5b9b1a06ce1 Mon Sep 17 00:00:00 2001
72332c
From: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
72332c
Date: Wed, 11 Jul 2018 13:43:33 +0300
72332c
Subject: [PATCH] mount: fix regression where open_mountpoint failed on
72332c
 readonly fs
72332c
72332c
If we fail to create temporary directory for doing a clean mount we can
72332c
make mount clean reusing the code which enters new mountns to umount
72332c
overmounts. As when last process exits mntns all mounts are implicitly
72332c
cleaned from children, see in kernel source - sys_exit->do_exit
72332c
->exit_task_namespaces->switch_task_namespaces->free_nsproxy
72332c
->put_mnt_ns->umount_tree->drop_collected_mounts->umount_tree:
72332c
72332c
    /* Hide the mounts from mnt_mounts */
72332c
    list_for_each_entry(p, &tmp_list, mnt_list) {
72332c
            list_del_init(&p->mnt_child);
72332c
    }
72332c
72332c
Fixes commit b6cfb1ce2948 ("mount: make open_mountpoint handle overmouts
72332c
properly")
72332c
72332c
https://github.com/checkpoint-restore/criu/issues/520
72332c
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
72332c
Acked-by: Adrian Reber <areber@redhat.com>
72332c
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
72332c
---
72332c
 criu/mount.c | 28 ++++++++++++++++++++--------
72332c
 1 file changed, 20 insertions(+), 8 deletions(-)
72332c
72332c
diff --git a/criu/mount.c b/criu/mount.c
72332c
index b56164e953..9cc8f6e940 100644
72332c
--- a/criu/mount.c
72332c
+++ b/criu/mount.c
72332c
@@ -1325,10 +1325,18 @@ int ns_open_mountpoint(void *arg)
72332c
 	if (umount_overmounts(mi))
72332c
 		goto err;
72332c
 
72332c
-	/* Save fd which we opened for parent due to CLONE_FILES flag */
72332c
-	*fd = get_clean_fd(mi);
72332c
-	if (*fd < 0)
72332c
+	/*
72332c
+	 * Save fd which we opened for parent due to CLONE_FILES flag
72332c
+	 *
72332c
+	 * Mount can still have children in it, but we don't need to clean it
72332c
+	 * explicitly as when last process exits mntns all mounts in it are
72332c
+	 * cleaned from their children, and we are exactly the last process.
72332c
+	 */
72332c
+	*fd = open(mi->mountpoint, O_DIRECTORY|O_RDONLY);
72332c
+	if (*fd < 0) {
72332c
+		pr_perror("Unable to open %s", mi->mountpoint);
72332c
 		goto err;
72332c
+	}
72332c
 
72332c
 	return 0;
72332c
 err:
72332c
@@ -1367,18 +1375,22 @@ int open_mountpoint(struct mount_info *pm)
72332c
 
72332c
 	if (!mnt_is_overmounted(pm)) {
72332c
 		pr_info("\tmount has children %s\n", pm->mountpoint);
72332c
-
72332c
 		fd = get_clean_fd(pm);
72332c
-		if (fd < 0)
72332c
-			goto err;
72332c
-	} else {
72332c
+	}
72332c
+
72332c
+	/*
72332c
+	 * Mount is overmounted or probably we can't create a temporary
72332c
+	 * direcotry for a cleaned mount
72332c
+	 */
72332c
+	if (fd < 0) {
72332c
 		int pid, status;
72332c
 		struct clone_arg ca = {
72332c
 			.mi = pm,
72332c
 			.fd = &fd
72332c
 		};
72332c
 
72332c
-		pr_info("\tmount is overmounted %s\n", pm->mountpoint);
72332c
+		pr_info("\tmount is overmounted or has children %s\n",
72332c
+				pm->mountpoint);
72332c
 
72332c
 		/*
72332c
 		 * We are overmounted - not accessible in a regular way. We