Commit 104d3b84 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

mount: rework can_mount_now() to support bind-mounts of shared mounts

Fedora bind-mounts a part of the root mount to itself. Currently we
don't allow to mount children of a shared mount, if other mount from
this shared group are not mounted.

This patch adds an exclusion for cases, when a child has the same
group. We allow to mount a child, if wider mounts are mounted.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent beeabc3b
......@@ -1468,28 +1468,11 @@ 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)
return -1;
/*
* Wait while all parent are not mounted
*
* FIXME a child is shared only between parents,
* who was present in a moment of birth
*/
if (mi->parent->flags & MS_SHARED) {
list_for_each_entry(t, &mi->parent->mnt_share, mnt_share) {
if (!t->mounted) {
pr_debug("\t\tPostpone %s due to %s\n",
mi->mountpoint, t->mountpoint);
return 1;
}
}
}
if (mount(src, mi->mountpoint, tp->name,
mi->flags & (~MS_SHARED), mi->options) < 0) {
pr_perror("Can't mount at %s", mi->mountpoint);
......@@ -1585,22 +1568,34 @@ static bool can_mount_now(struct mount_info *mi)
/* The root mount */
if (!mi->parent)
return true;
/*
* Private root mounts can be mounted at any time
*/
if (!mi->master_id && fsroot_mounted(mi))
if (mi->is_ns_root)
return true;
/*
* Other mounts can be mounted only if they have
* the master mount (see propagate_mount) or if we
* expect a plugin/ext-mount-map to help us.
*/
if (mi->bind || mi->need_plugin || mi->external)
return true;
if (mi->master_id && mi->bind == NULL)
return false;
if (!fsroot_mounted(mi) && (mi->bind == NULL && !mi->need_plugin && !mi->external))
return false;
if (mi->parent->shared_id) {
struct mount_info *p = mi->parent, *n;
return false;
if (mi->parent->shared_id == mi->shared_id) {
int rlen = strlen(mi->root);
list_for_each_entry(n, &p->mnt_share, mnt_share)
if (strlen(n->root) < rlen && !n->mounted)
return false;
} else {
list_for_each_entry(n, &p->mnt_share, mnt_share)
if (!n->mounted)
return false;
list_for_each_entry(n, &p->mnt_slave_list, mnt_slave)
if (!n->mounted)
return false;
}
}
return true;
}
static int do_mount_root(struct mount_info *mi)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment