diff --git a/block/bdev.c b/block/bdev.c index ed022f8c48c7..e0bace1a6c27 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -860,11 +860,6 @@ void blkdev_put_no_open(struct block_device *bdev) put_device(&bdev->bd_device); } -static bool bdev_writes_blocked(struct block_device *bdev) -{ - return bdev->bd_writers < 0; -} - static void bdev_block_writes(struct block_device *bdev) { bdev->bd_writers--; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0000913f7efc..34bbbf3bcb36 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1239,6 +1239,22 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) goto out_unlock; } +#ifndef CONFIG_BLK_DEV_WRITE_MOUNTED + /* + * Changing lo_offset or shrinking lo_sizelimit on a mounted + * device is equivalent to modifying the block device contents. + * Block this if writes to the device are blocked. + */ + if ((lo->lo_offset != info->lo_offset || + (info->lo_sizelimit && + (lo->lo_sizelimit == 0 || + info->lo_sizelimit < lo->lo_sizelimit))) && + bdev_writes_blocked(lo->lo_device)) { + err = -EBUSY; + goto out_unlock; + } +#endif + if (lo->lo_offset != info->lo_offset || lo->lo_sizelimit != info->lo_sizelimit) { size_changed = true; diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 8808ee76e73c..82ece8737b85 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -84,6 +84,11 @@ struct block_device { #define bdev_whole(_bdev) \ ((_bdev)->bd_disk->part0) +static inline bool bdev_writes_blocked(struct block_device *bdev) +{ + return bdev->bd_writers < 0; +} + #define dev_to_bdev(device) \ container_of((device), struct block_device, bd_device)