[patch 7/7] vfs: mountinfo: show dominating group id
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>
This commit is contained in:
parent
2d4d4864ac
commit
97e7e0f71d
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
51
fs/pnode.c
51
fs/pnode.c
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue