On 2022-07-28 05:07, Damien Le Moal wrote: > On 7/28/22 01:22, Pankaj Raghav wrote: >> Checking if a given sector is aligned to a zone is a common >> operation that is performed for zoned devices. Add >> bdev_is_zone_start helper to check for this instead of opencoding it > > The patch actually introduces bdev_is_zone_aligned(). I agree with Bart > that bdev_is_zone_start() is a better name. I have posted my rationale behind this change in my reply to Bart. Let me know what you think. > <snip> >> args->zone_sectors = zone->len; >> - args->nr_zones = (capacity + zone->len - 1) >> ilog2(zone->len); >> + args->nr_zones = div64_u64(capacity + zone->len - 1, zone->len); > > args->nr_zones = disk_zone_no(disk, capacity); > We are doing a round up with a division here mainly to take into account the last unequal zone if present. disk_zone_no does just a division so it won't account for the unequal last zone. >> } else if (zone->start + args->zone_sectors < capacity) { >> if (zone->len != args->zone_sectors) { >> pr_warn("%s: Invalid zoned device with non constant zone size\n", >> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h >> index 85b832908f28..1be805223026 100644 >> --- a/include/linux/blkdev.h >> +++ b/include/linux/blkdev.h >> @@ -634,6 +634,11 @@ static inline bool queue_is_mq(struct request_queue *q) >> return q->mq_ops; >> } >> >> +static inline struct request_queue *bdev_get_queue(struct block_device *bdev) >> +{ >> + return bdev->bd_queue; /* this is never NULL */ >> +} >> + >> #ifdef CONFIG_PM >> static inline enum rpm_status queue_rpm_status(struct request_queue *q) >> { >> @@ -665,6 +670,25 @@ static inline bool blk_queue_is_zoned(struct request_queue *q) >> } >> } >> >> +static inline bool bdev_is_zoned(struct block_device *bdev) >> +{ >> + struct request_queue *q = bdev_get_queue(bdev); >> + >> + if (q) >> + return blk_queue_is_zoned(q); >> + >> + return false; >> +} >> + >> +static inline sector_t bdev_zone_sectors(struct block_device *bdev) >> +{ >> + struct request_queue *q = bdev_get_queue(bdev); >> + >> + if (!blk_queue_is_zoned(q)) >> + return 0; >> + return q->limits.chunk_sectors; >> +} >> + >> #ifdef CONFIG_BLK_DEV_ZONED >> static inline unsigned int disk_nr_zones(struct gendisk *disk) >> { >> @@ -684,6 +708,30 @@ static inline unsigned int disk_zone_no(struct gendisk *disk, sector_t sector) >> return div64_u64(sector, zone_sectors); >> } >> >> +static inline sector_t bdev_offset_from_zone_start(struct block_device *bdev, >> + sector_t sec) >> +{ >> + sector_t zone_sectors = bdev_zone_sectors(bdev); >> + u64 remainder = 0; >> + >> + if (!bdev_is_zoned(bdev)) >> + return 0; >> + >> + if (is_power_of_2(zone_sectors)) >> + return sec & (zone_sectors - 1); >> + >> + div64_u64_rem(sec, zone_sectors, &remainder); >> + return remainder; >> +} >> + >> +static inline bool bdev_is_zone_aligned(struct block_device *bdev, sector_t sec) >> +{ >> + if (!bdev_is_zoned(bdev)) >> + return false; > > This is checked in bdev_offset_from_zone_start(). No need to add it again > here. > bdev_offset_from_zone_start returns 0 if the device is not zoned, and the below check will then return `true`. That is why I explicitly return a false if the device is not zoned. >> + >> + return bdev_offset_from_zone_start(bdev, sec) == 0; >> +} >> + >> static inline bool disk_zone_is_seq(struct gendisk *disk, sector_t sector) >> { >> if (!blk_queue_is_zoned(disk->queue)) >> @@ -728,6 +776,18 @@ static inline unsigned int disk_zone_no(struct gendisk *disk, sector_t sector) >> { >> return 0; >> } >> + >> +static inline sector_t bdev_offset_from_zone_start(struct block_device *bdev, >> + sector_t sec) >> +{ >> + return 0; >> +} > > This one is not used when CONFIG_BLK_DEV_ZONED is not set. No need to > define it. > Ok. I will remove it if it is not required. >> + >> +static inline bool bdev_is_zone_aligned(struct block_device *bdev, sector_t sec) >> +{ >