diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-12-22 23:04:31 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-12-22 23:04:31 -0500 |
commit | faf0dcebd7b387187f29ff811d47df465ea4c9f9 (patch) | |
tree | 77077e72fe22222a369aa36da2f12e064a91bbe9 | |
parent | 128394eff343fc6d2f32172f03e24829539c5835 (diff) | |
parent | 5235d448c48e1f5a4a34bf90d412775cb75ffb32 (diff) |
Merge branch 'work.namespace' into for-linus
-rw-r--r-- | fs/namespace.c | 8 | ||||
-rw-r--r-- | fs/pnode.c | 74 |
2 files changed, 38 insertions, 44 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index f7e28f8ea04d..b5b1259e064f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -96,10 +96,6 @@ static inline struct hlist_head *mp_hash(struct dentry *dentry) | |||
96 | return &mountpoint_hashtable[tmp & mp_hash_mask]; | 96 | return &mountpoint_hashtable[tmp & mp_hash_mask]; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* | ||
100 | * allocation is serialized by namespace_sem, but we need the spinlock to | ||
101 | * serialize with freeing. | ||
102 | */ | ||
103 | static int mnt_alloc_id(struct mount *mnt) | 99 | static int mnt_alloc_id(struct mount *mnt) |
104 | { | 100 | { |
105 | int res; | 101 | int res; |
@@ -1034,6 +1030,8 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
1034 | if (IS_MNT_SLAVE(old)) | 1030 | if (IS_MNT_SLAVE(old)) |
1035 | list_add(&mnt->mnt_slave, &old->mnt_slave); | 1031 | list_add(&mnt->mnt_slave, &old->mnt_slave); |
1036 | mnt->mnt_master = old->mnt_master; | 1032 | mnt->mnt_master = old->mnt_master; |
1033 | } else { | ||
1034 | CLEAR_MNT_SHARED(mnt); | ||
1037 | } | 1035 | } |
1038 | if (flag & CL_MAKE_SHARED) | 1036 | if (flag & CL_MAKE_SHARED) |
1039 | set_mnt_shared(mnt); | 1037 | set_mnt_shared(mnt); |
@@ -1828,9 +1826,7 @@ struct vfsmount *clone_private_mount(const struct path *path) | |||
1828 | if (IS_MNT_UNBINDABLE(old_mnt)) | 1826 | if (IS_MNT_UNBINDABLE(old_mnt)) |
1829 | return ERR_PTR(-EINVAL); | 1827 | return ERR_PTR(-EINVAL); |
1830 | 1828 | ||
1831 | down_read(&namespace_sem); | ||
1832 | new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE); | 1829 | new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE); |
1833 | up_read(&namespace_sem); | ||
1834 | if (IS_ERR(new_mnt)) | 1830 | if (IS_ERR(new_mnt)) |
1835 | return ERR_CAST(new_mnt); | 1831 | return ERR_CAST(new_mnt); |
1836 | 1832 | ||
diff --git a/fs/pnode.c b/fs/pnode.c index 234a9ac49958..06a793f4ae38 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -67,49 +67,47 @@ int get_dominating_id(struct mount *mnt, const struct path *root) | |||
67 | 67 | ||
68 | static int do_make_slave(struct mount *mnt) | 68 | static int do_make_slave(struct mount *mnt) |
69 | { | 69 | { |
70 | struct mount *peer_mnt = mnt, *master = mnt->mnt_master; | 70 | struct mount *master, *slave_mnt; |
71 | struct mount *slave_mnt; | ||
72 | 71 | ||
73 | /* | 72 | if (list_empty(&mnt->mnt_share)) { |
74 | * slave 'mnt' to a peer mount that has the | 73 | if (IS_MNT_SHARED(mnt)) { |
75 | * same root dentry. If none is available then | 74 | mnt_release_group_id(mnt); |
76 | * slave it to anything that is available. | 75 | CLEAR_MNT_SHARED(mnt); |
77 | */ | 76 | } |
78 | while ((peer_mnt = next_peer(peer_mnt)) != mnt && | 77 | master = mnt->mnt_master; |
79 | peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ; | 78 | if (!master) { |
80 | 79 | struct list_head *p = &mnt->mnt_slave_list; | |
81 | if (peer_mnt == mnt) { | 80 | while (!list_empty(p)) { |
82 | peer_mnt = next_peer(mnt); | 81 | slave_mnt = list_first_entry(p, |
83 | if (peer_mnt == mnt) | 82 | struct mount, mnt_slave); |
84 | peer_mnt = NULL; | 83 | list_del_init(&slave_mnt->mnt_slave); |
85 | } | 84 | slave_mnt->mnt_master = NULL; |
86 | if (mnt->mnt_group_id && IS_MNT_SHARED(mnt) && | 85 | } |
87 | list_empty(&mnt->mnt_share)) | 86 | return 0; |
88 | mnt_release_group_id(mnt); | 87 | } |
89 | |||
90 | list_del_init(&mnt->mnt_share); | ||
91 | mnt->mnt_group_id = 0; | ||
92 | |||
93 | if (peer_mnt) | ||
94 | master = peer_mnt; | ||
95 | |||
96 | if (master) { | ||
97 | list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) | ||
98 | slave_mnt->mnt_master = master; | ||
99 | list_move(&mnt->mnt_slave, &master->mnt_slave_list); | ||
100 | list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); | ||
101 | INIT_LIST_HEAD(&mnt->mnt_slave_list); | ||
102 | } else { | 88 | } else { |
103 | struct list_head *p = &mnt->mnt_slave_list; | 89 | struct mount *m; |
104 | while (!list_empty(p)) { | 90 | /* |
105 | slave_mnt = list_first_entry(p, | 91 | * slave 'mnt' to a peer mount that has the |
106 | struct mount, mnt_slave); | 92 | * same root dentry. If none is available then |
107 | list_del_init(&slave_mnt->mnt_slave); | 93 | * slave it to anything that is available. |
108 | slave_mnt->mnt_master = NULL; | 94 | */ |
95 | for (m = master = next_peer(mnt); m != mnt; m = next_peer(m)) { | ||
96 | if (m->mnt.mnt_root == mnt->mnt.mnt_root) { | ||
97 | master = m; | ||
98 | break; | ||
99 | } | ||
109 | } | 100 | } |
101 | list_del_init(&mnt->mnt_share); | ||
102 | mnt->mnt_group_id = 0; | ||
103 | CLEAR_MNT_SHARED(mnt); | ||
110 | } | 104 | } |
105 | list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) | ||
106 | slave_mnt->mnt_master = master; | ||
107 | list_move(&mnt->mnt_slave, &master->mnt_slave_list); | ||
108 | list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); | ||
109 | INIT_LIST_HEAD(&mnt->mnt_slave_list); | ||
111 | mnt->mnt_master = master; | 110 | mnt->mnt_master = master; |
112 | CLEAR_MNT_SHARED(mnt); | ||
113 | return 0; | 111 | return 0; |
114 | } | 112 | } |
115 | 113 | ||