Message ID | 20220615101920.329421-3-p.raghav@samsung.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v7,01/13] block: make blkdev_nr_zones and blk_queue_zone_no generic for npo2 zsze | expand |
On 6/15/22 03:19, Pankaj Raghav wrote: > @@ -489,14 +489,27 @@ 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); > + return -ENODEV; > + } > + > + /* > + * Don't allow zoned device with non power_of_2 zone size with > + * zone capacity less than zone size. > + */ Please change "power_of_2" into "power-of-2". > + if (!is_power_of_2(zone->len) && zone->capacity < zone->len) { > + pr_warn("%s: Invalid zone capacity for non power of 2 zone size", > + disk->disk_name); > return -ENODEV; > } The above check seems wrong to me. I don't see why devices that report a capacity that is less than the zone size should be rejected. > + /* > + * 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. > + */ Shouldn't the above comment be moved to the patch description? I'm not sure whether having such a comment in the source code is valuable. > +static inline sector_t blk_queue_offset_from_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; "return false" should only occur in functions returning a boolean. This function returns type sector_t. Thanks, Bart.
On 2022-06-15 22:28, Bart Van Assche wrote: isk_name, zone->len); >> + if (zone->len == 0) { >> + pr_warn("%s: Invalid zone size", disk->disk_name); >> + return -ENODEV; >> + } >> + >> + /* >> + * Don't allow zoned device with non power_of_2 zone size with >> + * zone capacity less than zone size. >> + */ > > Please change "power_of_2" into "power-of-2". > Ok. >> + if (!is_power_of_2(zone->len) && zone->capacity < zone->len) { >> + pr_warn("%s: Invalid zone capacity for non power of 2 >> zone size", >> + disk->disk_name); >> return -ENODEV; >> } > > The above check seems wrong to me. I don't see why devices that report a > capacity that is less than the zone size should be rejected. > This was brought up by Damien during previous reviews. The argument was that the reason to allow non power-of-2 zoned device is to remove the gaps between zone size and zone capacity. Allowing a npo2 zone size with a different capacity, even though it is technically possible, it does not make any practical sense. That is why this check was introduced. Does that answer your question? >> + /* >> + * 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. >> + */ > > Shouldn't the above comment be moved to the patch description? I'm not > sure whether having such a comment in the source code is valuable. > Yeah, I will remove it. Maybe it is very obvious at this point. >> +static inline sector_t blk_queue_offset_from_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; > > "return false" should only occur in functions returning a boolean. This > function returns type sector_t. > Good catch. It was a copy paste mistake. Fixed it. > Thanks, > > Bart.
On Thu, Jun 16, 2022 at 12:09:35PM +0200, Pankaj Raghav wrote: > On 2022-06-15 22:28, Bart Van Assche wrote: > >> + if (!is_power_of_2(zone->len) && zone->capacity < zone->len) { > >> + pr_warn("%s: Invalid zone capacity for non power of 2 > >> zone size", > >> + disk->disk_name); > >> return -ENODEV; > >> } > > > > The above check seems wrong to me. I don't see why devices that report a > > capacity that is less than the zone size should be rejected. > > > This was brought up by Damien during previous reviews. The argument was > that the reason to allow non power-of-2 zoned device is to remove the > gaps between zone size and zone capacity. Allowing a npo2 zone size with > a different capacity, even though it is technically possible, it does > not make any practical sense. That is why this check was introduced. > Does that answer your question? Perhaps just add a comment because unless you are involved in the prior reviews this might not be clear. Luis
On 6/16/22 19:09, Pankaj Raghav wrote: > On 2022-06-15 22:28, Bart Van Assche wrote: > isk_name, zone->len); >>> + if (zone->len == 0) { >>> + pr_warn("%s: Invalid zone size", disk->disk_name); >>> + return -ENODEV; >>> + } >>> + >>> + /* >>> + * Don't allow zoned device with non power_of_2 zone size with >>> + * zone capacity less than zone size. >>> + */ >> > >> Please change "power_of_2" into "power-of-2". >> > Ok. >>> + if (!is_power_of_2(zone->len) && zone->capacity < zone->len) { >>> + pr_warn("%s: Invalid zone capacity for non power of 2 >>> zone size", >>> + disk->disk_name); >>> return -ENODEV; >>> } >> >> The above check seems wrong to me. I don't see why devices that report a >> capacity that is less than the zone size should be rejected. >> > This was brought up by Damien during previous reviews. The argument was > that the reason to allow non power-of-2 zoned device is to remove the > gaps between zone size and zone capacity. Allowing a npo2 zone size with > a different capacity, even though it is technically possible, it does > not make any practical sense. That is why this check was introduced. > Does that answer your question? Add a comment explaining this restriction, clearly mentioning that it is a Linux restrictions and not mandated by the specifications. >>> + /* >>> + * 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. >>> + */ >> >> Shouldn't the above comment be moved to the patch description? I'm not >> sure whether having such a comment in the source code is valuable. >> > Yeah, I will remove it. Maybe it is very obvious at this point. >>> +static inline sector_t blk_queue_offset_from_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; >> >> "return false" should only occur in functions returning a boolean. This >> function returns type sector_t. >> > Good catch. It was a copy paste mistake. Fixed it. >> Thanks, >> >> Bart. > > -- > dm-devel mailing list > dm-devel@redhat.com > https://listman.redhat.com/mailman/listinfo/dm-devel
diff --git a/block/blk-core.c b/block/blk-core.c index 06ff5bbfe..248b947e5 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -629,8 +629,7 @@ static inline blk_status_t blk_check_zone_append(struct request_queue *q, return BLK_STS_NOTSUPP; /* The bio sector must point to the start of a sequential zone */ - if (pos & (blk_queue_zone_sectors(q) - 1) || - !blk_queue_zone_is_seq(q, pos)) + if (!blk_queue_is_zone_start(q, pos) || !blk_queue_zone_is_seq(q, pos)) return BLK_STS_IOERR; /* diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 8b0615287..7957eec04 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -288,10 +288,10 @@ int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op, return -EINVAL; /* Check alignment (handle eventual smaller last zone) */ - if (sector & (zone_sectors - 1)) + if (!blk_queue_is_zone_start(q, sector)) return -EINVAL; - if ((nr_sectors & (zone_sectors - 1)) && end_sector != capacity) + if (!blk_queue_is_zone_start(q, nr_sectors) && end_sector != capacity) return -EINVAL; /* @@ -489,14 +489,27 @@ 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); + 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 zone capacity for non power of 2 zone size", + disk->disk_name); 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. + */ + 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 39017ae9d..3c106dba1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -692,6 +692,27 @@ static inline unsigned int blk_queue_zone_no(struct request_queue *q, return div64_u64(sector, zone_sectors); } +static inline sector_t blk_queue_offset_from_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 sec & (zone_sectors - 1); + + div64_u64_rem(sec, zone_sectors, &remainder); + return remainder; +} + +static inline bool blk_queue_is_zone_start(struct request_queue *q, sector_t sec) +{ + return blk_queue_offset_from_zone_start(q, sec) == 0; +} + static inline bool blk_queue_zone_is_seq(struct request_queue *q, sector_t sector) { @@ -738,6 +759,18 @@ static inline unsigned int blk_queue_zone_no(struct request_queue *q, { return 0; } + +static inline sector_t blk_queue_offset_from_zone_start(struct request_queue *q, + sector_t sec) +{ + 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;