aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/pnode.c')
-rw-r--r--fs/pnode.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/fs/pnode.c b/fs/pnode.c
index 7bc942d047cd..f73eba24f1d1 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -17,13 +17,61 @@ static inline struct vfsmount *next_peer(struct vfsmount *p)
17 return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); 17 return list_entry(p->mnt_share.next, struct vfsmount, mnt_share);
18} 18}
19 19
20static int do_make_slave(struct vfsmount *mnt)
21{
22 struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master;
23 struct vfsmount *slave_mnt;
24
25 /*
26 * slave 'mnt' to a peer mount that has the
27 * same root dentry. If none is available than
28 * slave it to anything that is available.
29 */
30 while ((peer_mnt = next_peer(peer_mnt)) != mnt &&
31 peer_mnt->mnt_root != mnt->mnt_root) ;
32
33 if (peer_mnt == mnt) {
34 peer_mnt = next_peer(mnt);
35 if (peer_mnt == mnt)
36 peer_mnt = NULL;
37 }
38 list_del_init(&mnt->mnt_share);
39
40 if (peer_mnt)
41 master = peer_mnt;
42
43 if (master) {
44 list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave)
45 slave_mnt->mnt_master = master;
46 list_del(&mnt->mnt_slave);
47 list_add(&mnt->mnt_slave, &master->mnt_slave_list);
48 list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev);
49 INIT_LIST_HEAD(&mnt->mnt_slave_list);
50 } else {
51 struct list_head *p = &mnt->mnt_slave_list;
52 while (!list_empty(p)) {
53 slave_mnt = list_entry(p->next,
54 struct vfsmount, mnt_slave);
55 list_del_init(&slave_mnt->mnt_slave);
56 slave_mnt->mnt_master = NULL;
57 }
58 }
59 mnt->mnt_master = master;
60 CLEAR_MNT_SHARED(mnt);
61 INIT_LIST_HEAD(&mnt->mnt_slave_list);
62 return 0;
63}
64
20void change_mnt_propagation(struct vfsmount *mnt, int type) 65void change_mnt_propagation(struct vfsmount *mnt, int type)
21{ 66{
22 if (type == MS_SHARED) { 67 if (type == MS_SHARED) {
23 set_mnt_shared(mnt); 68 set_mnt_shared(mnt);
24 } else { 69 return;
25 list_del_init(&mnt->mnt_share); 70 }
26 mnt->mnt_flags &= ~MNT_PNODE_MASK; 71 do_make_slave(mnt);
72 if (type != MS_SLAVE) {
73 list_del_init(&mnt->mnt_slave);
74 mnt->mnt_master = NULL;
27 } 75 }
28} 76}
29 77