Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

block: Allow zero value of max_zone_append_sectors queue limit

In preparation for adding a generic zone append emulation using zone
write plugging, allow device drivers supporting zoned block device to
set a the max_zone_append_sectors queue limit of a device to 0 to
indicate the lack of native support for zone append operations and that
the block layer should emulate these operations using regular write
operations.

blk_queue_max_zone_append_sectors() is modified to allow passing 0 as
the max_zone_append_sectors argument. The function
queue_max_zone_append_sectors() is also modified to ensure that the
minimum of the max_hw_sectors and chunk_sectors limit is used whenever
the max_zone_append_sectors limit is 0. This minimum is consistent with
the value set for the max_zone_append_sectors limit by the function
blk_validate_zoned_limits() when limits for a queue are validated.

The helper functions queue_emulates_zone_append() and
bdev_emulates_zone_append() are added to test if a queue (or block
device) emulates zone append operations.

In order for blk_revalidate_disk_zones() to accept zoned block devices
relying on zone append emulation, the direct check to the
max_zone_append_sectors queue limit of the disk is replaced by a check
using the value returned by queue_max_zone_append_sectors(). Similarly,
queue_zone_append_max_show() is modified to use the same accessor so
that the sysfs attribute advertizes the non-zero limit that will be
used, regardless if it is for native or emulated commands.

For stacking drivers, a top device should not need to care if the
underlying devices have native or emulated zone append operations.
blk_stack_limits() is thus modified to set the top device
max_zone_append_sectors limit using the new accessor
queue_limits_max_zone_append_sectors(). queue_max_zone_append_sectors()
is modified to use this function as well. Stacking drivers that require
zone append emulation, e.g. dm-crypt, can still request this feature by
calling blk_queue_max_zone_append_sectors() with a 0 limit.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Tested-by: Hans Holmberg <hans.holmberg@wdc.com>
Tested-by: Dennis Maisenbacher <dennis.maisenbacher@wdc.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20240408014128.205141-10-dlemoal@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Damien Le Moal and committed by
Jens Axboe
ccdbf0aa 843283e9

+42 -17
+1 -1
block/blk-core.c
··· 602 602 return BLK_STS_IOERR; 603 603 604 604 /* Make sure the BIO is small enough and will not get split */ 605 - if (nr_sectors > q->limits.max_zone_append_sectors) 605 + if (nr_sectors > queue_max_zone_append_sectors(q)) 606 606 return BLK_STS_IOERR; 607 607 608 608 bio->bi_opf |= REQ_NOMERGE;
+19 -11
block/blk-settings.c
··· 412 412 * blk_queue_max_zone_append_sectors - set max sectors for a single zone append 413 413 * @q: the request queue for the device 414 414 * @max_zone_append_sectors: maximum number of sectors to write per command 415 + * 416 + * Sets the maximum number of sectors allowed for zone append commands. If 417 + * Specifying 0 for @max_zone_append_sectors indicates that the queue does 418 + * not natively support zone append operations and that the block layer must 419 + * emulate these operations using regular writes. 415 420 **/ 416 421 void blk_queue_max_zone_append_sectors(struct request_queue *q, 417 422 unsigned int max_zone_append_sectors) 418 423 { 419 - unsigned int max_sectors; 424 + unsigned int max_sectors = 0; 420 425 421 426 if (WARN_ON(!blk_queue_is_zoned(q))) 422 427 return; 423 428 424 - max_sectors = min(q->limits.max_hw_sectors, max_zone_append_sectors); 425 - max_sectors = min(q->limits.chunk_sectors, max_sectors); 429 + if (max_zone_append_sectors) { 430 + max_sectors = min(q->limits.max_hw_sectors, 431 + max_zone_append_sectors); 432 + max_sectors = min(q->limits.chunk_sectors, max_sectors); 426 433 427 - /* 428 - * Signal eventual driver bugs resulting in the max_zone_append sectors limit 429 - * being 0 due to a 0 argument, the chunk_sectors limit (zone size) not set, 430 - * or the max_hw_sectors limit not set. 431 - */ 432 - WARN_ON(!max_sectors); 434 + /* 435 + * Signal eventual driver bugs resulting in the max_zone_append 436 + * sectors limit being 0 due to the chunk_sectors limit (zone 437 + * size) not set or the max_hw_sectors limit not set. 438 + */ 439 + WARN_ON_ONCE(!max_sectors); 440 + } 433 441 434 442 q->limits.max_zone_append_sectors = max_sectors; 435 443 } ··· 764 756 t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors); 765 757 t->max_write_zeroes_sectors = min(t->max_write_zeroes_sectors, 766 758 b->max_write_zeroes_sectors); 767 - t->max_zone_append_sectors = min(t->max_zone_append_sectors, 768 - b->max_zone_append_sectors); 759 + t->max_zone_append_sectors = min(queue_limits_max_zone_append_sectors(t), 760 + queue_limits_max_zone_append_sectors(b)); 769 761 t->bounce = max(t->bounce, b->bounce); 770 762 771 763 t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
+1 -1
block/blk-sysfs.c
··· 224 224 225 225 static ssize_t queue_zone_append_max_show(struct request_queue *q, char *page) 226 226 { 227 - unsigned long long max_sectors = q->limits.max_zone_append_sectors; 227 + unsigned long long max_sectors = queue_max_zone_append_sectors(q); 228 228 229 229 return sprintf(page, "%llu\n", max_sectors << SECTOR_SHIFT); 230 230 }
+1 -1
block/blk-zoned.c
··· 1692 1692 return -ENODEV; 1693 1693 } 1694 1694 1695 - if (!q->limits.max_zone_append_sectors) { 1695 + if (!queue_max_zone_append_sectors(q)) { 1696 1696 pr_warn("%s: Invalid 0 maximum zone append limit\n", 1697 1697 disk->disk_name); 1698 1698 return -ENODEV;
+20 -3
include/linux/blkdev.h
··· 1173 1173 return q->limits.max_segment_size; 1174 1174 } 1175 1175 1176 - static inline unsigned int queue_max_zone_append_sectors(const struct request_queue *q) 1176 + static inline unsigned int queue_limits_max_zone_append_sectors(struct queue_limits *l) 1177 1177 { 1178 + unsigned int max_sectors = min(l->chunk_sectors, l->max_hw_sectors); 1178 1179 1179 - const struct queue_limits *l = &q->limits; 1180 + return min_not_zero(l->max_zone_append_sectors, max_sectors); 1181 + } 1180 1182 1181 - return min(l->max_zone_append_sectors, l->max_sectors); 1183 + static inline unsigned int queue_max_zone_append_sectors(struct request_queue *q) 1184 + { 1185 + if (!blk_queue_is_zoned(q)) 1186 + return 0; 1187 + 1188 + return queue_limits_max_zone_append_sectors(&q->limits); 1189 + } 1190 + 1191 + static inline bool queue_emulates_zone_append(struct request_queue *q) 1192 + { 1193 + return blk_queue_is_zoned(q) && !q->limits.max_zone_append_sectors; 1194 + } 1195 + 1196 + static inline bool bdev_emulates_zone_append(struct block_device *bdev) 1197 + { 1198 + return queue_emulates_zone_append(bdev_get_queue(bdev)); 1182 1199 } 1183 1200 1184 1201 static inline unsigned int