Skip to content

Commit bd32073

Browse files
committed
Merge patch series "fs: listmount()/statmount() fix and sample program"
Jeff Layton <[email protected]> says: We had some recent queries internally asking how to use the new statmount() and listmount() interfaces. I was doing some other work in this area, so I whipped up this tool. My hope is that this will represent something of a "rosetta stone" for how to translate between mountinfo and statmount(), and an example for other people looking to use the new interfaces. It may also be possible to use this as the basis for a listmount() and statmount() testcase. We can call this program, and compare its output to the mountinfo file. The second patch adds security mount options to the existing mnt_opts in the statmount() interface, which I think is the final missing piece here. The alternative to doing that would be to add a new string field for that, but I'm not sure that's worthwhile. * patches from https://lore.kernel.org/r/[email protected]: fs: prepend statmount.mnt_opts string with security_sb_mnt_opts() samples: add a mountinfo program to demonstrate statmount()/listmount() Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
2 parents 40384c8 + 056d331 commit bd32073

File tree

6 files changed

+296
-17
lines changed

6 files changed

+296
-17
lines changed

fs/mount.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct mount {
3838
struct dentry *mnt_mountpoint;
3939
struct vfsmount mnt;
4040
union {
41+
struct rb_node mnt_node; /* node in the ns->mounts rbtree */
4142
struct rcu_head mnt_rcu;
4243
struct llist_node mnt_llist;
4344
};
@@ -51,10 +52,7 @@ struct mount {
5152
struct list_head mnt_child; /* and going through their mnt_child */
5253
struct list_head mnt_instance; /* mount instance on sb->s_mounts */
5354
const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
54-
union {
55-
struct rb_node mnt_node; /* Under ns->mounts */
56-
struct list_head mnt_list;
57-
};
55+
struct list_head mnt_list;
5856
struct list_head mnt_expire; /* link in fs-specific expiry list */
5957
struct list_head mnt_share; /* circular list of shared mounts */
6058
struct list_head mnt_slave_list;/* list of slave mounts */
@@ -145,11 +143,16 @@ static inline bool is_anon_ns(struct mnt_namespace *ns)
145143
return ns->seq == 0;
146144
}
147145

146+
static inline bool mnt_ns_attached(const struct mount *mnt)
147+
{
148+
return !RB_EMPTY_NODE(&mnt->mnt_node);
149+
}
150+
148151
static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list)
149152
{
150-
WARN_ON(!(mnt->mnt.mnt_flags & MNT_ONRB));
151-
mnt->mnt.mnt_flags &= ~MNT_ONRB;
153+
WARN_ON(!mnt_ns_attached(mnt));
152154
rb_erase(&mnt->mnt_node, &mnt->mnt_ns->mounts);
155+
RB_CLEAR_NODE(&mnt->mnt_node);
153156
list_add_tail(&mnt->mnt_list, dt_list);
154157
}
155158

fs/namespace.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ static struct mount *alloc_vfsmnt(const char *name)
344344
INIT_HLIST_NODE(&mnt->mnt_mp_list);
345345
INIT_LIST_HEAD(&mnt->mnt_umounting);
346346
INIT_HLIST_HEAD(&mnt->mnt_stuck_children);
347+
RB_CLEAR_NODE(&mnt->mnt_node);
347348
mnt->mnt.mnt_idmap = &nop_mnt_idmap;
348349
}
349350
return mnt;
@@ -1124,7 +1125,7 @@ static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt)
11241125
struct rb_node **link = &ns->mounts.rb_node;
11251126
struct rb_node *parent = NULL;
11261127

1127-
WARN_ON(mnt->mnt.mnt_flags & MNT_ONRB);
1128+
WARN_ON(mnt_ns_attached(mnt));
11281129
mnt->mnt_ns = ns;
11291130
while (*link) {
11301131
parent = *link;
@@ -1135,7 +1136,6 @@ static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt)
11351136
}
11361137
rb_link_node(&mnt->mnt_node, parent, link);
11371138
rb_insert_color(&mnt->mnt_node, &ns->mounts);
1138-
mnt->mnt.mnt_flags |= MNT_ONRB;
11391139
}
11401140

11411141
/*
@@ -1305,7 +1305,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
13051305
}
13061306

13071307
mnt->mnt.mnt_flags = old->mnt.mnt_flags;
1308-
mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL|MNT_ONRB);
1308+
mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL);
13091309

13101310
atomic_inc(&sb->s_active);
13111311
mnt->mnt.mnt_idmap = mnt_idmap_get(mnt_idmap(&old->mnt));
@@ -1763,7 +1763,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
17631763
/* Gather the mounts to umount */
17641764
for (p = mnt; p; p = next_mnt(p, mnt)) {
17651765
p->mnt.mnt_flags |= MNT_UMOUNT;
1766-
if (p->mnt.mnt_flags & MNT_ONRB)
1766+
if (mnt_ns_attached(p))
17671767
move_from_ns(p, &tmp_list);
17681768
else
17691769
list_move(&p->mnt_list, &tmp_list);
@@ -1912,16 +1912,14 @@ static int do_umount(struct mount *mnt, int flags)
19121912

19131913
event++;
19141914
if (flags & MNT_DETACH) {
1915-
if (mnt->mnt.mnt_flags & MNT_ONRB ||
1916-
!list_empty(&mnt->mnt_list))
1915+
if (mnt_ns_attached(mnt) || !list_empty(&mnt->mnt_list))
19171916
umount_tree(mnt, UMOUNT_PROPAGATE);
19181917
retval = 0;
19191918
} else {
19201919
shrink_submounts(mnt);
19211920
retval = -EBUSY;
19221921
if (!propagate_mount_busy(mnt, 2)) {
1923-
if (mnt->mnt.mnt_flags & MNT_ONRB ||
1924-
!list_empty(&mnt->mnt_list))
1922+
if (mnt_ns_attached(mnt) || !list_empty(&mnt->mnt_list))
19251923
umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
19261924
retval = 0;
19271925
}
@@ -5038,6 +5036,10 @@ static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq)
50385036
if (sb->s_op->show_options) {
50395037
size_t start = seq->count;
50405038

5039+
err = security_sb_show_options(seq, sb);
5040+
if (err)
5041+
return err;
5042+
50415043
err = sb->s_op->show_options(seq, mnt->mnt_root);
50425044
if (err)
50435045
return err;

include/linux/mount.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ struct path;
5050
#define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME )
5151

5252
#define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \
53-
MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED | MNT_ONRB)
53+
MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED)
5454

5555
#define MNT_INTERNAL 0x4000
5656

@@ -64,7 +64,6 @@ struct path;
6464
#define MNT_SYNC_UMOUNT 0x2000000
6565
#define MNT_MARKED 0x4000000
6666
#define MNT_UMOUNT 0x8000000
67-
#define MNT_ONRB 0x10000000
6867

6968
struct vfsmount {
7069
struct dentry *mnt_root; /* root of the mounted tree */

samples/vfs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
/test-fsmount
33
/test-statx
4+
/mountinfo

samples/vfs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0-only
2-
userprogs-always-y += test-fsmount test-statx
2+
userprogs-always-y += test-fsmount test-statx mountinfo
33

44
userccflags += -I usr/include

0 commit comments

Comments
 (0)