diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-11-24 23:56:26 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-03 22:57:07 -0500 |
commit | c937135d98f2306157fb8d8a03a4d8b0f1e3b511 (patch) | |
tree | f5ba303add1b65d82b4d1b6443e1794a9d36fad7 /fs/pnode.c | |
parent | 6fc7871fed915914ef441efbe0f9a7c3d0f3bff1 (diff) |
vfs: spread struct mount - shared subtree iterators
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/pnode.c')
-rw-r--r-- | fs/pnode.c | 97 |
1 files changed, 47 insertions, 50 deletions
diff --git a/fs/pnode.c b/fs/pnode.c index 29e366dec024..f86cd4bc31ce 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -13,19 +13,19 @@ | |||
13 | #include "pnode.h" | 13 | #include "pnode.h" |
14 | 14 | ||
15 | /* return the next shared peer mount of @p */ | 15 | /* return the next shared peer mount of @p */ |
16 | static inline struct vfsmount *next_peer(struct vfsmount *p) | 16 | static inline struct mount *next_peer(struct mount *p) |
17 | { | 17 | { |
18 | return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); | 18 | return list_entry(p->mnt.mnt_share.next, struct mount, mnt.mnt_share); |
19 | } | 19 | } |
20 | 20 | ||
21 | static inline struct vfsmount *first_slave(struct vfsmount *p) | 21 | static inline struct mount *first_slave(struct mount *p) |
22 | { | 22 | { |
23 | return list_entry(p->mnt_slave_list.next, struct vfsmount, mnt_slave); | 23 | return list_entry(p->mnt.mnt_slave_list.next, struct mount, mnt.mnt_slave); |
24 | } | 24 | } |
25 | 25 | ||
26 | static inline struct vfsmount *next_slave(struct vfsmount *p) | 26 | static inline struct mount *next_slave(struct mount *p) |
27 | { | 27 | { |
28 | return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave); | 28 | return list_entry(p->mnt.mnt_slave.next, struct mount, mnt.mnt_slave); |
29 | } | 29 | } |
30 | 30 | ||
31 | static struct mount *get_peer_under_root(struct mount *mnt, | 31 | static struct mount *get_peer_under_root(struct mount *mnt, |
@@ -39,7 +39,7 @@ static struct mount *get_peer_under_root(struct mount *mnt, | |||
39 | if (m->mnt.mnt_ns == ns && is_path_reachable(m, m->mnt.mnt_root, root)) | 39 | if (m->mnt.mnt_ns == ns && is_path_reachable(m, m->mnt.mnt_root, root)) |
40 | return m; | 40 | return m; |
41 | 41 | ||
42 | m = real_mount(next_peer(&m->mnt)); | 42 | m = next_peer(m); |
43 | } while (m != mnt); | 43 | } while (m != mnt); |
44 | 44 | ||
45 | return NULL; | 45 | return NULL; |
@@ -74,11 +74,11 @@ static int do_make_slave(struct mount *mnt) | |||
74 | * same root dentry. If none is available then | 74 | * same root dentry. If none is available then |
75 | * slave it to anything that is available. | 75 | * slave it to anything that is available. |
76 | */ | 76 | */ |
77 | while ((peer_mnt = real_mount(next_peer(&peer_mnt->mnt))) != mnt && | 77 | while ((peer_mnt = next_peer(peer_mnt)) != mnt && |
78 | peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ; | 78 | peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ; |
79 | 79 | ||
80 | if (peer_mnt == mnt) { | 80 | if (peer_mnt == mnt) { |
81 | peer_mnt = real_mount(next_peer(&mnt->mnt)); | 81 | peer_mnt = next_peer(mnt); |
82 | if (peer_mnt == mnt) | 82 | if (peer_mnt == mnt) |
83 | peer_mnt = NULL; | 83 | peer_mnt = NULL; |
84 | } | 84 | } |
@@ -141,21 +141,20 @@ void change_mnt_propagation(struct mount *mnt, int type) | |||
141 | * vfsmount found while iterating with propagation_next() is | 141 | * vfsmount found while iterating with propagation_next() is |
142 | * a peer of one we'd found earlier. | 142 | * a peer of one we'd found earlier. |
143 | */ | 143 | */ |
144 | static struct vfsmount *propagation_next(struct vfsmount *m, | 144 | static struct mount *propagation_next(struct mount *m, |
145 | struct vfsmount *origin) | 145 | struct mount *origin) |
146 | { | 146 | { |
147 | /* are there any slaves of this mount? */ | 147 | /* are there any slaves of this mount? */ |
148 | if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) | 148 | if (!IS_MNT_NEW(&m->mnt) && !list_empty(&m->mnt.mnt_slave_list)) |
149 | return first_slave(m); | 149 | return first_slave(m); |
150 | 150 | ||
151 | while (1) { | 151 | while (1) { |
152 | struct vfsmount *next; | 152 | struct mount *master = real_mount(m->mnt.mnt_master); |
153 | struct vfsmount *master = m->mnt_master; | ||
154 | 153 | ||
155 | if (master == origin->mnt_master) { | 154 | if (&master->mnt == origin->mnt.mnt_master) { |
156 | next = next_peer(m); | 155 | struct mount *next = next_peer(m); |
157 | return ((next == origin) ? NULL : next); | 156 | return (next == origin) ? NULL : next; |
158 | } else if (m->mnt_slave.next != &master->mnt_slave_list) | 157 | } else if (m->mnt.mnt_slave.next != &master->mnt.mnt_slave_list) |
159 | return next_slave(m); | 158 | return next_slave(m); |
160 | 159 | ||
161 | /* back at master */ | 160 | /* back at master */ |
@@ -172,25 +171,25 @@ static struct vfsmount *propagation_next(struct vfsmount *m, | |||
172 | * @type return CL_SLAVE if the new mount has to be | 171 | * @type return CL_SLAVE if the new mount has to be |
173 | * cloned as a slave. | 172 | * cloned as a slave. |
174 | */ | 173 | */ |
175 | static struct vfsmount *get_source(struct vfsmount *dest, | 174 | static struct mount *get_source(struct mount *dest, |
176 | struct vfsmount *last_dest, | 175 | struct mount *last_dest, |
177 | struct vfsmount *last_src, | 176 | struct mount *last_src, |
178 | int *type) | 177 | int *type) |
179 | { | 178 | { |
180 | struct vfsmount *p_last_src = NULL; | 179 | struct mount *p_last_src = NULL; |
181 | struct vfsmount *p_last_dest = NULL; | 180 | struct mount *p_last_dest = NULL; |
182 | 181 | ||
183 | while (last_dest != dest->mnt_master) { | 182 | while (&last_dest->mnt != dest->mnt.mnt_master) { |
184 | p_last_dest = last_dest; | 183 | p_last_dest = last_dest; |
185 | p_last_src = last_src; | 184 | p_last_src = last_src; |
186 | last_dest = last_dest->mnt_master; | 185 | last_dest = real_mount(last_dest->mnt.mnt_master); |
187 | last_src = last_src->mnt_master; | 186 | last_src = real_mount(last_src->mnt.mnt_master); |
188 | } | 187 | } |
189 | 188 | ||
190 | if (p_last_dest) { | 189 | if (p_last_dest) { |
191 | do { | 190 | do { |
192 | p_last_dest = next_peer(p_last_dest); | 191 | p_last_dest = next_peer(p_last_dest); |
193 | } while (IS_MNT_NEW(p_last_dest)); | 192 | } while (IS_MNT_NEW(&p_last_dest->mnt)); |
194 | /* is that a peer of the earlier? */ | 193 | /* is that a peer of the earlier? */ |
195 | if (dest == p_last_dest) { | 194 | if (dest == p_last_dest) { |
196 | *type = CL_MAKE_SHARED; | 195 | *type = CL_MAKE_SHARED; |
@@ -200,7 +199,7 @@ static struct vfsmount *get_source(struct vfsmount *dest, | |||
200 | /* slave of the earlier, then */ | 199 | /* slave of the earlier, then */ |
201 | *type = CL_SLAVE; | 200 | *type = CL_SLAVE; |
202 | /* beginning of peer group among the slaves? */ | 201 | /* beginning of peer group among the slaves? */ |
203 | if (IS_MNT_SHARED(dest)) | 202 | if (IS_MNT_SHARED(&dest->mnt)) |
204 | *type |= CL_MAKE_SHARED; | 203 | *type |= CL_MAKE_SHARED; |
205 | return last_src; | 204 | return last_src; |
206 | } | 205 | } |
@@ -221,32 +220,31 @@ static struct vfsmount *get_source(struct vfsmount *dest, | |||
221 | int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, | 220 | int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, |
222 | struct vfsmount *source_mnt, struct list_head *tree_list) | 221 | struct vfsmount *source_mnt, struct list_head *tree_list) |
223 | { | 222 | { |
224 | struct vfsmount *m; | 223 | struct mount *m, *child; |
225 | struct mount *child; | ||
226 | int ret = 0; | 224 | int ret = 0; |
227 | struct vfsmount *prev_dest_mnt = dest_mnt; | 225 | struct mount *prev_dest_mnt = real_mount(dest_mnt); |
228 | struct vfsmount *prev_src_mnt = source_mnt; | 226 | struct mount *prev_src_mnt = real_mount(source_mnt); |
229 | LIST_HEAD(tmp_list); | 227 | LIST_HEAD(tmp_list); |
230 | LIST_HEAD(umount_list); | 228 | LIST_HEAD(umount_list); |
231 | 229 | ||
232 | for (m = propagation_next(dest_mnt, dest_mnt); m; | 230 | for (m = propagation_next(real_mount(dest_mnt), real_mount(dest_mnt)); m; |
233 | m = propagation_next(m, dest_mnt)) { | 231 | m = propagation_next(m, real_mount(dest_mnt))) { |
234 | int type; | 232 | int type; |
235 | struct vfsmount *source; | 233 | struct mount *source; |
236 | 234 | ||
237 | if (IS_MNT_NEW(m)) | 235 | if (IS_MNT_NEW(&m->mnt)) |
238 | continue; | 236 | continue; |
239 | 237 | ||
240 | source = get_source(m, prev_dest_mnt, prev_src_mnt, &type); | 238 | source = get_source(m, prev_dest_mnt, prev_src_mnt, &type); |
241 | 239 | ||
242 | if (!(child = copy_tree(real_mount(source), source->mnt_root, type))) { | 240 | if (!(child = copy_tree(source, source->mnt.mnt_root, type))) { |
243 | ret = -ENOMEM; | 241 | ret = -ENOMEM; |
244 | list_splice(tree_list, tmp_list.prev); | 242 | list_splice(tree_list, tmp_list.prev); |
245 | goto out; | 243 | goto out; |
246 | } | 244 | } |
247 | 245 | ||
248 | if (is_subdir(dest_dentry, m->mnt_root)) { | 246 | if (is_subdir(dest_dentry, m->mnt.mnt_root)) { |
249 | mnt_set_mountpoint(m, dest_dentry, child); | 247 | mnt_set_mountpoint(&m->mnt, dest_dentry, child); |
250 | list_add_tail(&child->mnt_hash, tree_list); | 248 | list_add_tail(&child->mnt_hash, tree_list); |
251 | } else { | 249 | } else { |
252 | /* | 250 | /* |
@@ -256,7 +254,7 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, | |||
256 | list_add_tail(&child->mnt_hash, &tmp_list); | 254 | list_add_tail(&child->mnt_hash, &tmp_list); |
257 | } | 255 | } |
258 | prev_dest_mnt = m; | 256 | prev_dest_mnt = m; |
259 | prev_src_mnt = &child->mnt; | 257 | prev_src_mnt = child; |
260 | } | 258 | } |
261 | out: | 259 | out: |
262 | br_write_lock(vfsmount_lock); | 260 | br_write_lock(vfsmount_lock); |
@@ -290,8 +288,7 @@ static inline int do_refcount_check(struct mount *mnt, int count) | |||
290 | */ | 288 | */ |
291 | int propagate_mount_busy(struct mount *mnt, int refcnt) | 289 | int propagate_mount_busy(struct mount *mnt, int refcnt) |
292 | { | 290 | { |
293 | struct vfsmount *m; | 291 | struct mount *m, *child; |
294 | struct mount *child; | ||
295 | struct mount *parent = mnt->mnt_parent; | 292 | struct mount *parent = mnt->mnt_parent; |
296 | int ret = 0; | 293 | int ret = 0; |
297 | 294 | ||
@@ -306,9 +303,9 @@ int propagate_mount_busy(struct mount *mnt, int refcnt) | |||
306 | if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt)) | 303 | if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt)) |
307 | return 1; | 304 | return 1; |
308 | 305 | ||
309 | for (m = propagation_next(&parent->mnt, &parent->mnt); m; | 306 | for (m = propagation_next(parent, parent); m; |
310 | m = propagation_next(m, &parent->mnt)) { | 307 | m = propagation_next(m, parent)) { |
311 | child = __lookup_mnt(m, mnt->mnt_mountpoint, 0); | 308 | child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint, 0); |
312 | if (child && list_empty(&child->mnt_mounts) && | 309 | if (child && list_empty(&child->mnt_mounts) && |
313 | (ret = do_refcount_check(child, 1))) | 310 | (ret = do_refcount_check(child, 1))) |
314 | break; | 311 | break; |
@@ -323,14 +320,14 @@ int propagate_mount_busy(struct mount *mnt, int refcnt) | |||
323 | static void __propagate_umount(struct mount *mnt) | 320 | static void __propagate_umount(struct mount *mnt) |
324 | { | 321 | { |
325 | struct mount *parent = mnt->mnt_parent; | 322 | struct mount *parent = mnt->mnt_parent; |
326 | struct vfsmount *m; | 323 | struct mount *m; |
327 | 324 | ||
328 | BUG_ON(parent == mnt); | 325 | BUG_ON(parent == mnt); |
329 | 326 | ||
330 | for (m = propagation_next(&parent->mnt, &parent->mnt); m; | 327 | for (m = propagation_next(parent, parent); m; |
331 | m = propagation_next(m, &parent->mnt)) { | 328 | m = propagation_next(m, parent)) { |
332 | 329 | ||
333 | struct mount *child = __lookup_mnt(m, | 330 | struct mount *child = __lookup_mnt(&m->mnt, |
334 | mnt->mnt_mountpoint, 0); | 331 | mnt->mnt_mountpoint, 0); |
335 | /* | 332 | /* |
336 | * umount the child only if the child has no | 333 | * umount the child only if the child has no |