Commit 69535342 authored by Pavel Tikhomirov's avatar Pavel Tikhomirov Committed by Andrei Vagin

mount: use propagation groups in propagate_mount replacing excess search

These also fixes false-propagation problem of the mount to itself if it
is in parent's share.
Signed-off-by: 's avatarPavel Tikhomirov <ptikhomirov@virtuozzo.com>
parent 545b0736
...@@ -2010,7 +2010,7 @@ static int propagate_siblings(struct mount_info *mi) ...@@ -2010,7 +2010,7 @@ static int propagate_siblings(struct mount_info *mi)
static int propagate_mount(struct mount_info *mi) static int propagate_mount(struct mount_info *mi)
{ {
struct mount_info *t; struct mount_info *p;
propagate_siblings(mi); propagate_siblings(mi);
...@@ -2019,47 +2019,21 @@ static int propagate_mount(struct mount_info *mi) ...@@ -2019,47 +2019,21 @@ static int propagate_mount(struct mount_info *mi)
umount_from_slaves(mi); umount_from_slaves(mi);
/* Propagate this mount to everyone from a parent group */ /* Mark mounts in propagation group mounted */
list_for_each_entry(p, &mi->mnt_propagate, mnt_propagate) {
list_for_each_entry(t, &mi->parent->mnt_share, mnt_share) { /* Should not propagate the same mount twice */
struct mount_info *c; BUG_ON(p->mounted);
char path[PATH_MAX], *mp; pr_debug("\t\tPropagate %s\n", p->mountpoint);
bool found = false;
/* /*
* If a mount from parent's shared group is not yet mounted * When a mount is propagated, the result mount
* it shouldn't have 'sibling' in it - see can_mount_now() * is always shared. If we want to get a private
* mount, we need to convert it.
*/ */
if (!t->mounted) restore_shared_options(p, !p->shared_id, 0, 0);
continue; p->mounted = true;
propagate_siblings(p);
mp = mnt_get_sibling_path(mi, t, path, sizeof(path)); umount_from_slaves(p);
if (mp == NULL)
continue;
list_for_each_entry(c, &t->children, siblings) {
if (mounts_equal(mi, c) && !strcmp(mp, c->mountpoint)) {
/* Should not propagate the same mount twice */
BUG_ON(c->mounted);
pr_debug("\t\tPropagate %s\n", c->mountpoint);
/*
* When a mount is propagated, the result mount
* is always shared. If we want to get a private
* mount, we need to convert it.
*/
restore_shared_options(c, !c->shared_id, 0, 0);
c->mounted = true;
propagate_siblings(c);
umount_from_slaves(c);
found = true;
}
}
if (!found) {
pr_err("Unable to find %s\n", mp);
return -1;
}
} }
skip_parent: skip_parent:
...@@ -2068,6 +2042,8 @@ skip_parent: ...@@ -2068,6 +2042,8 @@ skip_parent:
* only if a proper root mount exists * only if a proper root mount exists
*/ */
if (fsroot_mounted(mi) || mi->parent == root_yard_mp || mi->external) { if (fsroot_mounted(mi) || mi->parent == root_yard_mp || mi->external) {
struct mount_info *t;
list_for_each_entry(t, &mi->mnt_bind, mnt_bind) { list_for_each_entry(t, &mi->mnt_bind, mnt_bind) {
if (t->mounted) if (t->mounted)
continue; continue;
......
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