From f4cc1c3810a0382ff76a4e119a21b90b84dbe195 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 19 Nov 2016 22:37:03 -0500 Subject: remove a bogus claim about namespace_sem being held by callers of mnt_alloc_id() Hadn't been true for quite a while Signed-off-by: Al Viro --- fs/namespace.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs') diff --git a/fs/namespace.c b/fs/namespace.c index e6c234b..a1a04dd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -96,10 +96,6 @@ static inline struct hlist_head *mp_hash(struct dentry *dentry) return &mountpoint_hashtable[tmp & mp_hash_mask]; } -/* - * allocation is serialized by namespace_sem, but we need the spinlock to - * serialize with freeing. - */ static int mnt_alloc_id(struct mount *mnt) { int res; -- cgit v1.1 From 066715d3fde4834cbbec88d12ca277c4185b9303 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 19 Nov 2016 23:23:18 -0500 Subject: clone_private_mount() doesn't need to touch namespace_sem not for CL_PRIVATE clone_mnt() Signed-off-by: Al Viro --- fs/namespace.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs') diff --git a/fs/namespace.c b/fs/namespace.c index a1a04dd..ec726ae 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1795,9 +1795,7 @@ struct vfsmount *clone_private_mount(struct path *path) if (IS_MNT_UNBINDABLE(old_mnt)) return ERR_PTR(-EINVAL); - down_read(&namespace_sem); new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE); - up_read(&namespace_sem); if (IS_ERR(new_mnt)) return ERR_CAST(new_mnt); -- cgit v1.1 From 5235d448c48e1f5a4a34bf90d412775cb75ffb32 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 20 Nov 2016 19:33:09 -0500 Subject: reorganize do_make_slave() Make sure that clone_mnt() never returns a mount with MNT_SHARED in flags, but without a valid ->mnt_group_id. That allows to demystify do_make_slave() quite a bit, among other things. Signed-off-by: Al Viro --- fs/namespace.c | 2 ++ fs/pnode.c | 74 ++++++++++++++++++++++++++++------------------------------ 2 files changed, 38 insertions(+), 38 deletions(-) (limited to 'fs') diff --git a/fs/namespace.c b/fs/namespace.c index ec726ae..141d577 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1030,6 +1030,8 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, if (IS_MNT_SLAVE(old)) list_add(&mnt->mnt_slave, &old->mnt_slave); mnt->mnt_master = old->mnt_master; + } else { + CLEAR_MNT_SHARED(mnt); } if (flag & CL_MAKE_SHARED) set_mnt_shared(mnt); diff --git a/fs/pnode.c b/fs/pnode.c index 234a9ac..06a793f 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -67,49 +67,47 @@ int get_dominating_id(struct mount *mnt, const struct path *root) static int do_make_slave(struct mount *mnt) { - struct mount *peer_mnt = mnt, *master = mnt->mnt_master; - struct mount *slave_mnt; + struct mount *master, *slave_mnt; - /* - * slave 'mnt' to a peer mount that has the - * same root dentry. If none is available then - * slave it to anything that is available. - */ - while ((peer_mnt = next_peer(peer_mnt)) != mnt && - peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ; - - if (peer_mnt == mnt) { - peer_mnt = next_peer(mnt); - if (peer_mnt == mnt) - peer_mnt = NULL; - } - if (mnt->mnt_group_id && IS_MNT_SHARED(mnt) && - list_empty(&mnt->mnt_share)) - mnt_release_group_id(mnt); - - list_del_init(&mnt->mnt_share); - mnt->mnt_group_id = 0; - - if (peer_mnt) - master = peer_mnt; - - if (master) { - list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) - slave_mnt->mnt_master = master; - list_move(&mnt->mnt_slave, &master->mnt_slave_list); - list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); - INIT_LIST_HEAD(&mnt->mnt_slave_list); + if (list_empty(&mnt->mnt_share)) { + if (IS_MNT_SHARED(mnt)) { + mnt_release_group_id(mnt); + CLEAR_MNT_SHARED(mnt); + } + master = mnt->mnt_master; + if (!master) { + struct list_head *p = &mnt->mnt_slave_list; + while (!list_empty(p)) { + slave_mnt = list_first_entry(p, + struct mount, mnt_slave); + list_del_init(&slave_mnt->mnt_slave); + slave_mnt->mnt_master = NULL; + } + return 0; + } } else { - struct list_head *p = &mnt->mnt_slave_list; - while (!list_empty(p)) { - slave_mnt = list_first_entry(p, - struct mount, mnt_slave); - list_del_init(&slave_mnt->mnt_slave); - slave_mnt->mnt_master = NULL; + struct mount *m; + /* + * slave 'mnt' to a peer mount that has the + * same root dentry. If none is available then + * slave it to anything that is available. + */ + for (m = master = next_peer(mnt); m != mnt; m = next_peer(m)) { + if (m->mnt.mnt_root == mnt->mnt.mnt_root) { + master = m; + break; + } } + list_del_init(&mnt->mnt_share); + mnt->mnt_group_id = 0; + CLEAR_MNT_SHARED(mnt); } + list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) + slave_mnt->mnt_master = master; + list_move(&mnt->mnt_slave, &master->mnt_slave_list); + list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); + INIT_LIST_HEAD(&mnt->mnt_slave_list); mnt->mnt_master = master; - CLEAR_MNT_SHARED(mnt); return 0; } -- cgit v1.1