[CRIU] [PATCH 3/4] mount: create a clean mount only when it's required
Andrey Vagin
avagin at openvz.org
Thu May 12 15:34:56 PDT 2016
From: Andrei Vagin <avagin at virtuozzo.com>
"clean mount" is a copy of target mount without child mounts.
Currently a clean mount is created when a target mount has children.
In this case a target path MAY be overmounted.
In this patch, a clean mount is created only if a target path is
overmounted. For that we enumerate all children and check that they
are not mounted over a target path.
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
criu/mount.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/criu/mount.c b/criu/mount.c
index f38ba1c..ec81351 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -2464,13 +2464,14 @@ static int do_bind_mount(struct mount_info *mi)
char mnt_fd_path[PSFDS];
char *root, *cut_root, rpath[PATH_MAX];
unsigned long mflags;
- int exit_code = -1;
+ int exit_code = -1, mp_len;
bool shared = false;
bool master = false;
bool private = false;
char *mnt_path = NULL;
struct stat st;
bool umount_mnt_path = false;
+ struct mount_info *c;
if (mi->need_plugin) {
if (restore_ext_mount(mi))
@@ -2503,14 +2504,30 @@ static int do_bind_mount(struct mount_info *mi)
mi->private = mi->bind->private;
mnt_path = mi->bind->mountpoint;
+
+ /* Access a mount by fd if mi->bind->mountpoint is overmounted */
if (mi->bind->fd >= 0) {
snprintf(mnt_fd_path, sizeof(mnt_fd_path),
"/proc/self/fd/%d", mi->bind->fd);
mnt_path = mnt_fd_path;
}
- if (!list_empty(&mi->bind->children)) {
- /* mi->bind->mountpoint may be overmounted */
+ if (cut_root[0] == 0) /* This case is handled by mi->bind->fd */
+ goto skip_overmount_check;
+
+ mp_len = strlen(mi->bind->mountpoint);
+ if (mp_len > 1) /* skip a joining / if mi->bind->mountpoint isn't "/" */
+ mp_len++;
+
+ list_for_each_entry(c, &mi->bind->children, siblings) {
+ if (!c->mounted)
+ continue;
+ if (issubpath(cut_root, c->mountpoint + mp_len))
+ break; /* a source path is overmounted */
+ }
+
+ if (&c->siblings != &mi->bind->children) {
+ /* Get a copy of mi->bind without child mounts */
if (mount(mnt_path, mnt_clean_path, NULL, MS_BIND, NULL)) {
pr_perror("Unable to bind-mount %s to %s",
mi->bind->mountpoint, mnt_clean_path);
@@ -2518,9 +2535,11 @@ static int do_bind_mount(struct mount_info *mi)
mnt_path = mnt_clean_path;
umount_mnt_path = true;
}
+
if (mnt_path == NULL)
return -1;
+skip_overmount_check:
snprintf(rpath, sizeof(rpath), "%s/%s",
mnt_path, cut_root);
root = rpath;
--
2.7.4
More information about the CRIU
mailing list