block: fix bd_size_lock use
authorDamien Le Moal <damien.lemoal@wdc.com>
Thu, 28 Jan 2021 06:36:19 +0000 (15:36 +0900)
committerJens Axboe <axboe@kernel.dk>
Thu, 28 Jan 2021 14:31:50 +0000 (07:31 -0700)
Some block device drivers, e.g. the skd driver, call set_capacity() with
IRQ disabled. This results in lockdep ito complain about inconsistent
lock states ("inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage")
because set_capacity takes a block device bd_size_lock using the
functions spin_lock() and spin_unlock(). Ensure a consistent locking
state by replacing these calls with spin_lock_irqsave() and
spin_lock_irqrestore(). The same applies to bdev_set_nr_sectors().
With this fix, all lockdep complaints are resolved.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/genhd.c
block/partitions/core.c

index 419548e..9e741a4 100644 (file)
@@ -45,10 +45,11 @@ static void disk_release_events(struct gendisk *disk);
 void set_capacity(struct gendisk *disk, sector_t sectors)
 {
        struct block_device *bdev = disk->part0;
+       unsigned long flags;
 
-       spin_lock(&bdev->bd_size_lock);
+       spin_lock_irqsave(&bdev->bd_size_lock, flags);
        i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
-       spin_unlock(&bdev->bd_size_lock);
+       spin_unlock_irqrestore(&bdev->bd_size_lock, flags);
 }
 EXPORT_SYMBOL(set_capacity);
 
index 23460ce..4601a84 100644 (file)
@@ -88,9 +88,11 @@ static int (*check_part[])(struct parsed_partitions *) = {
 
 static void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors)
 {
-       spin_lock(&bdev->bd_size_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bdev->bd_size_lock, flags);
        i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
-       spin_unlock(&bdev->bd_size_lock);
+       spin_unlock_irqrestore(&bdev->bd_size_lock, flags);
 }
 
 static struct parsed_partitions *allocate_partitions(struct gendisk *hd)