From: Yu Kuai <yukuai3@xxxxxxxxxx> If device support rename, for example dm, following concurrent scenario is possible: t1: mount t2: rename mount_bdev blkdev_get_by_path lookup_bdev(path, &dev); dm_rename // change device name blkdev_get_by_dev ... vfs_create_mount alloc_vfsmnt // mnt->mnt_devname is set to old name Test cmd: dmsetup create test1 --table "0 100000 linear /dev/sda 0" mkfs.ext2 -F /dev/mapper/test1 mount /dev/mapper/test1 /mnt/test & dmsetup rename test1 test2 Test result(If the above scenario triggers): mount will show test1 is mounted: [root@localhost ~]# mount | grep test /dev/mapper/test1 on /mnt/test type ext2 (rw,relatime,errors=continue,user_xattr,acl) while lsblk show test2 is mounted: [root@localhost ~]# lsblk /dev/sda NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk └─test2 252:0 0 48.8M 0 dm /mnt/test Furthermore, if a new device with name test1 is created, lsblk will show that it's mounted: [root@localhost ~]# dmsetup create test1 --table "0 100000 linear /dev/sdb 0" && lsblk /dev/sdb NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdb 8:16 0 10G 0 disk └─test1 252:1 0 48.8M 0 dm /mnt/test Fix the problem by checking dev_name again after bdev if found by blkdev_get_by_path() in mount_bdev(). Signed-off-by: Yu Kuai <yukuai3@xxxxxxxxxx> --- changes in v2: rebase to latest version fs/super.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/fs/super.c b/fs/super.c index 734ed584a946..c738da299fc1 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1341,6 +1341,20 @@ static int test_bdev_super(struct super_block *s, void *data) return !(s->s_iflags & SB_I_RETIRED) && (void *)s->s_bdev == data; } +static int check_dev_name(struct block_device *bdev, const char *dev_name) +{ + dev_t dev; + int error = lookup_bdev(dev_name, &dev); + + if (error) + return error; + + if (dev != bdev->bd_dev) + return -EBUSY; + + return 0; +} + struct dentry *mount_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, int (*fill_super)(struct super_block *, void *, int)) @@ -1357,6 +1371,15 @@ struct dentry *mount_bdev(struct file_system_type *fs_type, if (IS_ERR(bdev)) return ERR_CAST(bdev); + /* + * Some drivers support device rename, for example dm, make sure the + * right bdev is found, otherwise inconsistent device and mountpoint + * will be shown in /proc/mounts. + */ + error = check_dev_name(bdev, dev_name); + if (error) + goto error_bdev; + /* * once the super is inserted into the list by sget, s_umount * will protect the lockfs code from trying to start a snapshot -- 2.31.1