aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/proc.txt6
-rw-r--r--fs/namespace.c9
-rw-r--r--fs/pnode.c51
-rw-r--r--fs/pnode.h1
4 files changed, 65 insertions, 2 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 2cd920f92e5e..2a99116edc47 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -2374,8 +2374,14 @@ possible optional fields are:
2374 2374
2375shared:X mount is shared in peer group X 2375shared:X mount is shared in peer group X
2376master:X mount is slave to peer group X 2376master:X mount is slave to peer group X
2377propagate_from:X mount is slave and receives propagation from peer group X (*)
2377unbindable mount is unbindable 2378unbindable mount is unbindable
2378 2379
2380(*) X is the closest dominant peer group under the process's root. If
2381X is the immediate master of the mount, or if there's no dominant peer
2382group under the same root, then only the "master:X" field is present
2383and not the "propagate_from:X" field.
2384
2379For more information on mount propagation see: 2385For more information on mount propagation see:
2380 2386
2381 Documentation/filesystems/sharedsubtree.txt 2387 Documentation/filesystems/sharedsubtree.txt
diff --git a/fs/namespace.c b/fs/namespace.c
index c807b8d5f891..0505fb61aa74 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -850,8 +850,13 @@ static int show_mountinfo(struct seq_file *m, void *v)
850 /* Tagged fields ("foo:X" or "bar") */ 850 /* Tagged fields ("foo:X" or "bar") */
851 if (IS_MNT_SHARED(mnt)) 851 if (IS_MNT_SHARED(mnt))
852 seq_printf(m, " shared:%i", mnt->mnt_group_id); 852 seq_printf(m, " shared:%i", mnt->mnt_group_id);
853 if (IS_MNT_SLAVE(mnt)) 853 if (IS_MNT_SLAVE(mnt)) {
854 seq_printf(m, " master:%i", mnt->mnt_master->mnt_group_id); 854 int master = mnt->mnt_master->mnt_group_id;
855 int dom = get_dominating_id(mnt, &p->root);
856 seq_printf(m, " master:%i", master);
857 if (dom && dom != master)
858 seq_printf(m, " propagate_from:%i", dom);
859 }
855 if (IS_MNT_UNBINDABLE(mnt)) 860 if (IS_MNT_UNBINDABLE(mnt))
856 seq_puts(m, " unbindable"); 861 seq_puts(m, " unbindable");
857 862
diff --git a/fs/pnode.c b/fs/pnode.c
index d18d66491a01..8d5f392ec3d3 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -28,6 +28,57 @@ static inline struct vfsmount *next_slave(struct vfsmount *p)
28 return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave); 28 return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave);
29} 29}
30 30
31/*
32 * Return true if path is reachable from root
33 *
34 * namespace_sem is held, and mnt is attached
35 */
36static bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
37 const struct path *root)
38{
39 while (mnt != root->mnt && mnt->mnt_parent != mnt) {
40 dentry = mnt->mnt_mountpoint;
41 mnt = mnt->mnt_parent;
42 }
43 return mnt == root->mnt && is_subdir(dentry, root->dentry);
44}
45
46static struct vfsmount *get_peer_under_root(struct vfsmount *mnt,
47 struct mnt_namespace *ns,
48 const struct path *root)
49{
50 struct vfsmount *m = mnt;
51
52 do {
53 /* Check the namespace first for optimization */
54 if (m->mnt_ns == ns && is_path_reachable(m, m->mnt_root, root))
55 return m;
56
57 m = next_peer(m);
58 } while (m != mnt);
59
60 return NULL;
61}
62
63/*
64 * Get ID of closest dominating peer group having a representative
65 * under the given root.
66 *
67 * Caller must hold namespace_sem
68 */
69int get_dominating_id(struct vfsmount *mnt, const struct path *root)
70{
71 struct vfsmount *m;
72
73 for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) {
74 struct vfsmount *d = get_peer_under_root(m, mnt->mnt_ns, root);
75 if (d)
76 return d->mnt_group_id;
77 }
78
79 return 0;
80}
81
31static int do_make_slave(struct vfsmount *mnt) 82static int do_make_slave(struct vfsmount *mnt)
32{ 83{
33 struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master; 84 struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master;
diff --git a/fs/pnode.h b/fs/pnode.h
index 973c3f825e7d..958665d662af 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -36,4 +36,5 @@ int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
36int propagate_umount(struct list_head *); 36int propagate_umount(struct list_head *);
37int propagate_mount_busy(struct vfsmount *, int); 37int propagate_mount_busy(struct vfsmount *, int);
38void mnt_release_group_id(struct vfsmount *); 38void mnt_release_group_id(struct vfsmount *);
39int get_dominating_id(struct vfsmount *mnt, const struct path *root);
39#endif /* _LINUX_PNODE_H */ 40#endif /* _LINUX_PNODE_H */