[CRIU] [PATCH 3/4] mount: fix restoring a bind-mount when its root is overmounted
Andrey Vagin
avagin at openvz.org
Fri Dec 4 03:38:04 PST 2015
From: Andrew Vagin <avagin at virtuozzo.com>
In this case we mount source mount in a temporary place and use it to
create the bind-mount.
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
mount.c | 49 +++++++++++++++++++++++++++++++++++++------------
1 file changed, 37 insertions(+), 12 deletions(-)
diff --git a/mount.c b/mount.c
index bd5a7b9..842b5d4 100644
--- a/mount.c
+++ b/mount.c
@@ -2023,11 +2023,16 @@ static int restore_ext_mount(struct mount_info *mi)
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];
bool force_private_remount = false;
unsigned long mflags;
+ int exit_code = -1;
bool shared = 0;
+ char *mnt_path;
struct stat st;
+ bool umount_mnt_path = false;
if (mi->need_plugin) {
if (restore_ext_mount(mi))
@@ -2050,8 +2055,17 @@ static int do_bind_mount(struct mount_info *mi)
shared = mi->shared_id && mi->shared_id == mi->bind->shared_id;
cut_root = cut_root_for_bind(mi->root, mi->bind->root);
- snprintf(rpath, sizeof(rpath), "%s/%s",
- mi->bind->mountpoint, cut_root);
+ if (list_empty(&mi->bind->children))
+ mnt_path = mi->bind->mountpoint;
+ else {
+ mnt_path = get_clean_mnt(mi->bind, mnt_path_tmp, mnt_path_root);
+ umount_mnt_path = true;
+ }
+ if (mnt_path == NULL)
+ return -1;
+
+ snprintf(rpath, sizeof(rpath), "%s/%s/.",
+ mnt_path, cut_root);
root = rpath;
do_bind:
pr_info("\tBind %s to %s\n", root, mi->mountpoint);
@@ -2059,51 +2073,51 @@ do_bind:
if (unlikely(mi->deleted)) {
if (stat(mi->mountpoint, &st)) {
pr_perror("Can't fetch stat on %s", mi->mountpoint);
- return -1;
+ goto err;
}
if (S_ISDIR(st.st_mode)) {
if (mkdir(root, (st.st_mode & ~S_IFMT))) {
pr_perror("Can't re-create deleted directory %s", root);
- return -1;
+ goto err;
}
} else if (S_ISREG(st.st_mode)) {
int fd = open(root, O_WRONLY | O_CREAT | O_EXCL,
st.st_mode & ~S_IFMT);
if (fd < 0) {
pr_perror("Can't re-create deleted file %s", root);
- return -1;
+ goto err;
}
close(fd);
} else {
pr_err("Unsupported st_mode 0%o deleted root %s\n",
(int)st.st_mode, root);
- return -1;
+ goto err;
}
}
if (mount(root, mi->mountpoint, NULL, MS_BIND, NULL) < 0) {
pr_perror("Can't mount at %s", mi->mountpoint);
- return -1;
+ goto err;
}
mflags = mi->flags & (~MS_PROPAGATE);
if (!mi->bind || mflags != (mi->bind->flags & (~MS_PROPAGATE)))
if (mount(NULL, mi->mountpoint, NULL, MS_BIND | MS_REMOUNT | mflags, NULL)) {
pr_perror("Can't mount at %s", mi->mountpoint);
- return -1;
+ goto err;
}
if (unlikely(mi->deleted)) {
if (S_ISDIR(st.st_mode)) {
if (rmdir(root)) {
pr_perror("Can't remove deleted directory %s", root);
- return -1;
+ goto err;
}
} else if (S_ISREG(st.st_mode)) {
if (unlink(root)) {
pr_perror("Can't unlink deleted file %s", root);
- return -1;
+ goto err;
}
}
}
@@ -2118,8 +2132,19 @@ out:
return -1;
mi->mounted = true;
-
- return 0;
+ exit_code = 0;
+err:
+ if (umount_mnt_path) {
+ if (umount(mnt_path)) {
+ 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;
}
static bool can_mount_now(struct mount_info *mi)
--
2.4.3
More information about the CRIU
mailing list