[CRIU] [PATCH 5/9] mounts: handle bind-mounts
Andrey Vagin
avagin at openvz.org
Tue Jul 9 07:05:52 EDT 2013
A non-root mount is bind-mounted to a proper root mount.
Non-root mount without root mount is not supported yet
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
include/proc_parse.h | 2 ++
mount.c | 75 +++++++++++++++++++++++++++++++++++++---------------
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/include/proc_parse.h b/include/proc_parse.h
index 99255c4..1325424 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -114,9 +114,11 @@ struct mount_info {
/* tree linkage */
struct mount_info *parent;
+ struct mount_info *bind;
struct list_head children;
struct list_head siblings;
+ struct list_head mnt_bind;
struct list_head mnt_share; /* circular list of shared mounts */
struct list_head mnt_slave_list;/* list of slave mounts */
struct list_head mnt_slave; /* slave list entry */
diff --git a/mount.c b/mount.c
index 640cd12..31b1f3c 100644
--- a/mount.c
+++ b/mount.c
@@ -77,6 +77,16 @@ struct mount_info *lookup_mnt_sdev(unsigned int s_dev)
return NULL;
}
+/* two bind-mounts are reported as equal if bind is true */
+static bool mntcmp(struct mount_info* mi, struct mount_info *c, bool bind)
+{
+ return (mi->s_dev == c->s_dev &&
+ (bind || !strcmp(c->root, mi->root)) &&
+ !strcmp(c->source, mi->source) &&
+ !strcmp(c->options, mi->options) &&
+ c->fstype == mi->fstype);
+}
+
static struct mount_info *mnt_build_ids_tree(struct mount_info *list)
{
struct mount_info *m, *root = NULL;
@@ -178,6 +188,21 @@ static void mnt_tree_show(struct mount_info *tree, int off)
pr_info("%*s<--\n", off, "");
}
+static inline int is_root(char *p)
+{
+ return p[0] == '/' && p[1] == '\0';
+}
+
+static inline int is_root_mount(struct mount_info *mi)
+{
+ return is_root(mi->mountpoint);
+}
+
+static inline int fsroot_mounted(struct mount_info *mi)
+{
+ return is_root(mi->root);
+}
+
static int collect_shared(struct mount_info *info)
{
struct mount_info *m, *t;
@@ -197,6 +222,7 @@ static int collect_shared(struct mount_info *info)
for (t = info; t && (share || master); t = t->next) {
if (t == m)
continue;
+
if (master && t->shared_id == m->master_id) {
pr_debug("The mount %d is slave for %d\n", m->mnt_id, t->mnt_id);
list_add(&m->mnt_slave, &t->mnt_slave_list);
@@ -211,13 +237,20 @@ static int collect_shared(struct mount_info *info)
list_add(&m->mnt_share, &t->mnt_share);
}
}
- if (!master)
- continue;
- pr_err("Mount %d (master_id: %d shared_id: %d) "
- "has unreachable sharing\n", m->mnt_id,
- m->master_id, m->shared_id);
- return -1;
+ if (master) {
+ pr_err("Mount %d (master_id: %d shared_id: %d) "
+ "has unreachable sharing\n", m->mnt_id,
+ m->master_id, m->shared_id);
+ return -1;
+ }
+
+ /* Search bind-mounts */
+ if (list_empty(&m->mnt_bind))
+ for (t = m->next; t; t = t->next) {
+ if (mntcmp(m, t, true))
+ list_add(&t->mnt_bind, &m->mnt_bind);
+ }
}
return 0;
@@ -432,16 +465,6 @@ static struct fstype *decode_fstype(u32 fst)
return &fstypes[fst];
}
-static inline int is_root(char *p)
-{
- return p[0] == '/' && p[1] == '\0';
-}
-
-static inline int is_root_mount(struct mount_info *mi)
-{
- return is_root(mi->mountpoint);
-}
-
static int dump_one_mountpoint(struct mount_info *pm, int fd)
{
MntEntry me = MNT_ENTRY__INIT;
@@ -565,6 +588,7 @@ static int do_new_mount(struct mount_info *mi)
{
char *src;
struct fstype *tp = mi->fstype;
+ struct mount_info *t;
src = resolve_source(mi);
if (!src)
@@ -579,18 +603,24 @@ static int do_new_mount(struct mount_info *mi)
if (tp->restore && tp->restore(mi))
return -1;
+ list_for_each_entry(t, &mi->mnt_bind, mnt_bind)
+ t->bind = mi;
+
return 0;
}
static int do_bind_mount(struct mount_info *mi)
{
- pr_err("No bind mounts at %s\n", mi->mountpoint);
- return -1;
-}
+ char rpath[PATH_MAX];
-static inline int fsroot_mounted(struct mount_info *mi)
-{
- return is_root(mi->root);
+ snprintf(rpath, sizeof(rpath), "%s%s", mi->bind->mountpoint, mi->root);
+
+ if (mount(rpath, mi->mountpoint, NULL,
+ MS_BIND, NULL) < 0) {
+ pr_perror("Can't mount at %s", mi->mountpoint);
+ return -1;
+ }
+ return 0;
}
static int do_mount_one(struct mount_info *mi)
@@ -704,6 +734,7 @@ struct mount_info *mnt_entry_alloc()
INIT_LIST_HEAD(&new->siblings);
INIT_LIST_HEAD(&new->mnt_slave_list);
INIT_LIST_HEAD(&new->mnt_share);
+ INIT_LIST_HEAD(&new->mnt_bind);
new->mnt_master = NULL;
}
return new;
--
1.8.3.1
More information about the CRIU
mailing list