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