Any BIO targeting an offline zone of a zoned block device will fail, including read commands. So there is no point in issuing read BIOs. Fail these read operations early if we ever see one. Signed-off-by: Damien Le Moal --- block/blk-core.c | 3 +++ block/blk-zoned.c | 18 ++++++++++++++++++ block/blk.h | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/block/blk-core.c b/block/blk-core.c index 13dc70e8f55d..d420c80d2d93 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -866,6 +866,9 @@ void submit_bio_noacct(struct bio *bio) switch (bio_op(bio)) { case REQ_OP_READ: + if (bdev_is_zoned(bdev) && + bdev_zone_is_offline(bdev, bio->bi_iter.bi_sector)) + goto end_io; break; case REQ_OP_WRITE: if (bio->bi_opf & REQ_ATOMIC) { diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 19268afb8752..131c9f50b3da 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -308,6 +308,24 @@ bool bdev_zone_is_seq(struct block_device *bdev, sector_t sector) } EXPORT_SYMBOL_GPL(bdev_zone_is_seq); +/** + * bdev_zone_is_offline - check if a sector belongs to an offline zone + * @bdev: block device to check + * @sector: sector number + * + * Check if @sector on @bdev is contained in an offline zone. + */ +bool bdev_zone_is_offline(struct block_device *bdev, sector_t sector) +{ + enum blk_zone_cond cond; + + if (!bdev_is_zoned(bdev)) + return false; + + cond = disk_zone_get_cond(bdev->bd_disk, sector); + return cond == BLK_ZONE_COND_OFFLINE; +} + /** * bdev_zone_mgmt_allowed - check if management operations are allowed on a zone * @bdev: block device to check diff --git a/block/blk.h b/block/blk.h index 2cc03aa54c53..c2d07347a3ad 100644 --- a/block/blk.h +++ b/block/blk.h @@ -578,6 +578,7 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, unsigned int cmd, int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode, unsigned int cmd, unsigned long arg); bool bdev_zone_mgmt_allowed(struct block_device *bdev, sector_t sector); +bool bdev_zone_is_offline(struct block_device *bdev, sector_t sector); #else /* CONFIG_BLK_DEV_ZONED */ static inline void disk_init_zone_resources(struct gendisk *disk) { @@ -625,6 +626,11 @@ static inline bool bdev_zone_mgmt_allowed(struct block_device *bdev, { return false; } +static inline bool bdev_zone_is_offline(struct block_device *bdev, + sector_t sector) +{ + return false; +} #endif /* CONFIG_BLK_DEV_ZONED */ struct block_device *bdev_alloc(struct gendisk *disk, u8 partno); -- 2.55.0