[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