Hi Damien, I copied your comments from the previous thread to avoid confusion. On 2022-05-16 16:00, Damien Le Moal wrote: > On 2022/05/16 15:39, Pankaj Raghav wrote: >> Checking if a given sector is aligned to a zone is a common >> operation that is performed for zoned devices. Add >> blk_queue_is_zone_start helper to check for this instead of opencoding it >> everywhere. >> >> Convert the calculations on zone size to be generic instead of relying on >> power_of_2 based logic in the block layer using the helpers wherever >> possible. >> >> @@ -490,14 +490,29 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, >> * smaller last zone. >> */ >> if (zone->start == 0) { >> - if (zone->len == 0 || !is_power_of_2(zone->len)) { >> - pr_warn("%s: Invalid zoned device with non power of two zone size (%llu)\n", >> - disk->disk_name, zone->len); >> + if (zone->len == 0) { >> + pr_warn("%s: Invalid zone size", >> + disk->disk_name); > > This fits on one line, no ? > Yeah. I don't know why my formatter decided to do that. I will fix it. Thanks. >> + return -ENODEV; >> + } >> + >> + /* >> + * Don't allow zoned device with non power_of_2 zone size with >> + * zone capacity less than zone size. >> + */ >> + if (!is_power_of_2(zone->len) && >> + zone->capacity < zone->len) { >> + pr_warn("%s: Invalid zoned size with non power of 2 zone size and zone capacity < zone size", >> + disk->disk_name); > > Very long... What about: > > pr_warn("%s: Invalid zone capacity for non power of 2 zone size", > disk->disk_name); > This looks better. I will fix it up! >> return -ENODEV; >> } >> >> args->zone_sectors = zone->len; >> - args->nr_zones = (capacity + zone->len - 1) >> ilog2(zone->len); >> + /* >> + * Division is used to calculate nr_zones for both power_of_2 >> + * and non power_of_2 zone sizes as it is not in the hot path. >> + */ > > This comment is not very useful. > I also saw you mentioning the comment was not useful in nvme code for a similar scenario. Hannes brought up a point about making it explicit when we are not using any special path for power of 2 zone sizes as in most cases we do branching if the zone size is power of 2 to avoid division. >> + args->nr_zones = div64_u64(capacity + zone->len - 1, zone->len); >> } 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 22fe512ee..32d7bd7b1 100644 >> --- a/include/linux/blkdev.h >> +++ b/include/linux/blkdev.h >> @@ -686,6 +686,22 @@ static inline unsigned int blk_queue_zone_no(struct request_queue *q, >> return div64_u64(sector, zone_sectors); >> } >> >> +static inline bool blk_queue_is_zone_start(struct request_queue *q, sector_t sec) >> +{ >> + sector_t zone_sectors = blk_queue_zone_sectors(q); >> + u64 remainder = 0; >> + >> + if (!blk_queue_is_zoned(q)) >> + return false; >> + >> + if (is_power_of_2(zone_sectors)) >> + return IS_ALIGNED(sec, zone_sectors); >> + >> + div64_u64_rem(sec, zone_sectors, &remainder); >> + /* if there is a remainder, then the sector is not aligned */ > > Hmmm... Fairly obvious. Not sure this comment is useful. > True. I will remove it. >> + return remainder == 0; >> +} >> + >> static inline bool blk_queue_zone_is_seq(struct request_queue *q, >> sector_t sector) >> { >> @@ -732,6 +748,12 @@ static inline unsigned int blk_queue_zone_no(struct request_queue *q, >> { >> return 0; >> } >> + >> +static inline bool blk_queue_is_zone_start(struct request_queue *q, sector_t sec) >> +{ >> + return false; >> +} >> + >> static inline unsigned int queue_max_open_zones(const struct request_queue *q) >> { >> return 0; > >