Skip to content

Commit

Permalink
[patch 7/7] vfs: mountinfo: show dominating group id
Browse files Browse the repository at this point in the history
Show peer group ID of nearest dominating group that has intersection
with the mount's namespace.

Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Miklos Szeredi authored and Al Viro committed Apr 23, 2008
1 parent 2d4d486 commit 97e7e0f
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 2 deletions.
6 changes: 6 additions & 0 deletions Documentation/filesystems/proc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2374,8 +2374,14 @@ possible optional fields are:

shared:X mount is shared in peer group X
master:X mount is slave to peer group X
propagate_from:X mount is slave and receives propagation from peer group X (*)
unbindable mount is unbindable

(*) X is the closest dominant peer group under the process's root. If
X is the immediate master of the mount, or if there's no dominant peer
group under the same root, then only the "master:X" field is present
and not the "propagate_from:X" field.

For more information on mount propagation see:

Documentation/filesystems/sharedsubtree.txt
Expand Down
9 changes: 7 additions & 2 deletions fs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,8 +850,13 @@ static int show_mountinfo(struct seq_file *m, void *v)
/* Tagged fields ("foo:X" or "bar") */
if (IS_MNT_SHARED(mnt))
seq_printf(m, " shared:%i", mnt->mnt_group_id);
if (IS_MNT_SLAVE(mnt))
seq_printf(m, " master:%i", mnt->mnt_master->mnt_group_id);
if (IS_MNT_SLAVE(mnt)) {
int master = mnt->mnt_master->mnt_group_id;
int dom = get_dominating_id(mnt, &p->root);
seq_printf(m, " master:%i", master);
if (dom && dom != master)
seq_printf(m, " propagate_from:%i", dom);
}
if (IS_MNT_UNBINDABLE(mnt))
seq_puts(m, " unbindable");

Expand Down
51 changes: 51 additions & 0 deletions fs/pnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,57 @@ static inline struct vfsmount *next_slave(struct vfsmount *p)
return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave);
}

/*
* Return true if path is reachable from root
*
* namespace_sem is held, and mnt is attached
*/
static bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
const struct path *root)
{
while (mnt != root->mnt && mnt->mnt_parent != mnt) {
dentry = mnt->mnt_mountpoint;
mnt = mnt->mnt_parent;
}
return mnt == root->mnt && is_subdir(dentry, root->dentry);
}

static struct vfsmount *get_peer_under_root(struct vfsmount *mnt,
struct mnt_namespace *ns,
const struct path *root)
{
struct vfsmount *m = mnt;

do {
/* Check the namespace first for optimization */
if (m->mnt_ns == ns && is_path_reachable(m, m->mnt_root, root))
return m;

m = next_peer(m);
} while (m != mnt);

return NULL;
}

/*
* Get ID of closest dominating peer group having a representative
* under the given root.
*
* Caller must hold namespace_sem
*/
int get_dominating_id(struct vfsmount *mnt, const struct path *root)
{
struct vfsmount *m;

for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) {
struct vfsmount *d = get_peer_under_root(m, mnt->mnt_ns, root);
if (d)
return d->mnt_group_id;
}

return 0;
}

static int do_make_slave(struct vfsmount *mnt)
{
struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master;
Expand Down
1 change: 1 addition & 0 deletions fs/pnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
int propagate_umount(struct list_head *);
int propagate_mount_busy(struct vfsmount *, int);
void mnt_release_group_id(struct vfsmount *);
int get_dominating_id(struct vfsmount *mnt, const struct path *root);
#endif /* _LINUX_PNODE_H */

0 comments on commit 97e7e0f

Please sign in to comment.