[CRIU] [PATCH 4/4] mount: don't use a shared mount to get a clean mount
Andrey Vagin
avagin at openvz.org
Wed Mar 2 23:00:15 PST 2016
From: Andrew Vagin <avagin at virtuozzo.com>
When we bind-mount something into a shared mount,
a new mount will be shared too.
By default /tmp is a shared mount, so when we get a "clean mount",
it will be always shared. On restore we don't need this side effect,
so let's do bind-mount in a private mount.
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
criu/mount.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 57 insertions(+), 8 deletions(-)
diff --git a/criu/mount.c b/criu/mount.c
index 20a95d1..bac42e1 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -2279,10 +2279,51 @@ static int restore_ext_mount(struct mount_info *mi)
return ret;
}
+static char mnt_clean_path[] = "/tmp/cr-tmpfs.XXXXXX";
+
+static int mount_clean_path()
+{
+ /*
+ * To make a bind mount, we need to have access to a source directory,
+ * which can be over-mounted. The idea is to mount a source mount in
+ * an intermediate place without MS_REC and then create a target mounts.
+ * This intermediate place should be a private mount to not affect
+ * properties of the source mount.
+ */
+ if (mkdtemp(mnt_clean_path) == NULL) {
+ pr_perror("Unable to create a temporary directory");
+ return -1;
+ }
+
+ if (mount(mnt_clean_path, mnt_clean_path, NULL, MS_BIND, NULL)) {
+ pr_perror("Unable to mount tmpfs into %s", mnt_clean_path);
+ return -1;
+ }
+
+ if (mount(NULL, mnt_clean_path, NULL, MS_PRIVATE, NULL)) {
+ pr_perror("Unable to mark %s as private", mnt_clean_path);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int umount_clean_path()
+{
+ if (umount2(mnt_clean_path, MNT_DETACH)) {
+ pr_perror("Unable to umount %s\n", mnt_clean_path);
+ return -1;
+ }
+
+ if (rmdir(mnt_clean_path)) {
+ pr_perror("Unable to remove %s", mnt_clean_path);
+ }
+
+ return 0;
+}
+
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];
unsigned long mflags;
int exit_code = -1;
@@ -2321,7 +2362,11 @@ static int do_bind_mount(struct mount_info *mi)
mnt_path = mi->bind->mountpoint;
else {
/* mi->bind->mountpoint may be overmounted */
- mnt_path = get_clean_mnt(mi->bind, mnt_path_tmp, mnt_path_root);
+ if (mount(mi->bind->mountpoint, mnt_clean_path, NULL, MS_BIND, NULL)) {
+ pr_perror("Unable to bind-mount %s to %s",
+ mi->bind->mountpoint, mnt_clean_path);
+ }
+ mnt_path = mnt_clean_path;
umount_mnt_path = true;
}
if (mnt_path == NULL)
@@ -2410,10 +2455,6 @@ err:
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;
}
@@ -3025,6 +3066,7 @@ static int populate_mnt_ns(void)
struct mount_info *pms;
struct ns_id *nsid;
struct mount_info *roots_mp = NULL;
+ int ret;
if (mnt_roots) {
/* mnt_roots is a tmpfs mount and it's private */
@@ -3069,7 +3111,14 @@ static int populate_mnt_ns(void)
if (populate_roots_yard())
return -1;
- return mnt_tree_for_each(pms, do_mount_one);
+ if (mount_clean_path())
+ return -1;
+
+ ret = mnt_tree_for_each(pms, do_mount_one);
+
+ if (umount_clean_path())
+ return -1;
+ return ret;
}
int depopulate_roots_yard(void)
--
2.5.0
More information about the CRIU
mailing list