• H
    blk: reuse lookup_sem to serialize partition operations · 253d38f9
    Hou Tao 提交于
    hulk inclusion
    category: bugfix
    bugzilla: 55097
    CVE: NA
    
    -------------------------------------------------
    
    Now there no protection between partition operations (e.g, partition
    rescan) and delete_partition() in del_gendisk(), so the following
    scenario is possible:
    
    CPU 1
    
    blkdev_ioctl                   del_gendisk
      blkdev_reread_part
        lock bd_mutex
          drop_partitions
            check_partition
                                     lock lookup_sem
    				 // for each partition
    				 deletion_partion
    
            // for each partition
            add_partition
    
    The newly added partitions, the device files (e.g, /dev/sdXN)
    and the symlinks in /sys/class/block will be left behind. If
    the deleted disk is online again, the scan of partition will
    fail with the following error:
    
      sysfs: cannot create duplicate filename '/class/block/sdaN'
      sdX: pN could not be added: 17
    
    Vanilla kernel tries to fix that by commit c76f48eb
    ("block: take bd_mutex around delete_partitions in del_gendisk"),
    but it introduces dead-lock for nbd/loop/xen-frontblk drivers.
    These in-tree drivers can be fixed, but there may be other affected
    block drivers, especially the out-of-tree ones, so fixing it in
    another way.
    
    Two methods are considered. The first is waiting for the end
    of partition operations in del_gendisk(). It is OK but it needs
    adding new fields in gendisk (bool & wait_queue_head_t). The second
    is reusing lookup_sem and GENHD_FL_UP to serialize partition operations
    and del_gendisk(). Now the latter is chose and here are the details.
    
    There are six partition operations:
    
    (1) add_partition() in blkpg_ioctl()
    (2) deletion_partion() in blkpg_ioctl()
    (3) resize in blkpg_ioctl()
    (4) partition rescan in __blkdev_reread_part()
    (5) partition revalidate in bdev_disk_changed()
    (6) deletion_partion() in del_gendisk()
    
    op (1)~(5) already take bd_mutex, so using down_read() to
    serialize with down_write() in del_gendisk() is OK. op (3)
    only updates the values in hd_struct, so no lock is needed,
    because it already increase the ref of hd_struct.
    
    lookup_sem is used to prevent a newly-created blocking device inode from
    associating with a deleting gendisk, and the locking order is:
    
      part->bd_mutex -> disk->lookup_sem
        or
      whole->bd_mutex -> disk->lookup_sem
    
    Now it is also used to serialize the partition operations and the new
    locking order will be:
    
      part->bd_mutex -> whole->bd_mutex -> disk->lookup_sem
    
    and it is OK.
    Signed-off-by: NHou Tao <houtao1@huawei.com>
    Reviewed-by: NJason Yan <yanaijie@huawei.com>
    Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
    253d38f9
block_dev.c 57.6 KB