• Jan Kara's avatar
    blockdev: Avoid two active bdev inodes for one device · 560e7cb2
    Jan Kara authored
    When blkdev_open() races with device removal and creation it can happen
    that unhashed bdev inode gets associated with newly created gendisk
    like:
    
    CPU0					CPU1
    blkdev_open()
      bdev = bd_acquire()
    					del_gendisk()
    					  bdev_unhash_inode(bdev);
    					remove device
    					create new device with the same number
      __blkdev_get()
        disk = get_gendisk()
          - gets reference to gendisk of the new device
    
    Now another blkdev_open() will not find original 'bdev' as it got
    unhashed, create a new one and associate it with the same 'disk' at
    which point problems start as we have two independent page caches for
    one device.
    
    Fix the problem by verifying that the bdev inode didn't get unhashed
    before we acquired gendisk reference. That way we make sure gendisk can
    get associated only with visible bdev inodes.
    Tested-by: default avatarHou Tao <houtao1@huawei.com>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
    560e7cb2
block_dev.c 53.7 KB