/proc/$PID/mountinfo contains a field for the device number of the filesystem at each mount. This is taken from the superblock ->s_dev field, which is correct for every filesystem except btrfs. A btrfs filesystem can contain multiple subvols which each have a different device number. If (a directory within) one of these subvols is mounted, the device number reported in mountinfo will be different from the device number reported by stat(). This confuses some libraries and tools such as, historically, findmnt. Current findmnt seems to cope with the strangeness. So instead of using ->s_dev, call vfs_getattr_nosec() and use the ->dev provided. As there is no STATX flag to ask for the device number, we pass a request mask for zero, and also ask the filesystem to avoid syncing with any remote service. Signed-off-by: NeilBrown <neilb@xxxxxxx> --- fs/proc_namespace.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 392ef5162655..f342a0231e9e 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c @@ -138,10 +138,16 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) struct mount *r = real_mount(mnt); struct super_block *sb = mnt->mnt_sb; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; + struct kstat stat; int err; + /* We only want ->dev, and there is no STATX flag for that, + * so ask for nothing and assume we get ->dev + */ + vfs_getattr_nosec(&mnt_path, &stat, 0, AT_STATX_DONT_SYNC); + seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id, - MAJOR(sb->s_dev), MINOR(sb->s_dev)); + MAJOR(stat.dev), MINOR(stat.dev)); if (sb->s_op->show_path) { err = sb->s_op->show_path(m, mnt->mnt_root); if (err)