History

block: introduce zone_write_granularity limit

Per ZBC and ZAC specifications, host-managed SMR hard-disks mandate that all writes into sequential write required zones be aligned to the device physical block size. However, NVMe ZNS does not have this constraint and allows write operations into sequential zones to be aligned to the device logical block size. This inconsistency does not help with software portability across device types. To solve this, introduce the zone_write_granularity queue limit to indicate the alignment constraint, in bytes, of write operations into zones of a zoned block device. This new limit is exported as a read-only sysfs queue attribute and the helper blk_queue_zone_write_granularity() introduced for drivers to set this limit. The function blk_queue_set_zoned() is modified to set this new limit to the device logical block size by default. NVMe ZNS devices as well as zoned nullb devices use this default value as is. The scsi disk driver is modified to execute the blk_queue_zone_write_granularity() helper to set the zone write granularity of host-managed SMR disks to the disk physical block size. The accessor functions queue_zone_write_granularity() and bdev_zone_write_granularity() are also introduced.

Damien Le Moal committed 5 years ago

Commit a805a4f1 parent eafc63a5 files · +74 −1Browse files

Unified · Split

5 files
  1. Documentation/block/queue-sysfs.rst +7 −0
  2. block/blk-settings.c +36 −1
  3. block/blk-sysfs.c +8 −0
  4. drivers/scsi/sd_zbc.c +8 −0
  5. include/linux/blkdev.h +15 −0
Documentation/block/queue-sysfs.rst+7−0
@@ -279,4 +279,11 @@ devices are described in the ZBC (Zoned Block Commands) and ZAC · 278 unmodified lines
279do not support zone commands, they will be treated as regular block devices279do not support zone commands, they will be treated as regular block devices
280and zoned will report "none".280and zoned will report "none".
281 281
282zone_write_granularity (RO)
283---------------------------
284This indicates the alignment constraint, in bytes, for write operations in
285sequential zones of zoned block devices (devices with a zoned attributed
286that reports "host-managed" or "host-aware"). This value is always 0 for
287regular block devices.
288
282Jens Axboe <jens.axboe@oracle.com>, February 2009289Jens Axboe <jens.axboe@oracle.com>, February 2009
block/blk-settings.c+36−1
@@ -60,6 +60,7 @@ void blk_set_default_limits(struct queue_limits *lim) · 59 unmodified lines
60 lim->io_opt = 0;60 lim->io_opt = 0;
61 lim->misaligned = 0;61 lim->misaligned = 0;
62 lim->zoned = BLK_ZONED_NONE;62 lim->zoned = BLK_ZONED_NONE;
63 lim->zone_write_granularity = 0;
63}64}
64EXPORT_SYMBOL(blk_set_default_limits);65EXPORT_SYMBOL(blk_set_default_limits);
65 66
@@ -366,6 +367,28 @@ void blk_queue_physical_block_size(struct request_queue *q, unsigned int size) · 300 unmodified lines
366}367}
367EXPORT_SYMBOL(blk_queue_physical_block_size);368EXPORT_SYMBOL(blk_queue_physical_block_size);
368 369
370/**
371 * blk_queue_zone_write_granularity - set zone write granularity for the queue
372 * @q: the request queue for the zoned device
373 * @size: the zone write granularity size, in bytes
374 *
375 * Description:
376 * This should be set to the lowest possible size allowing to write in
377 * sequential zones of a zoned block device.
378 */
379void blk_queue_zone_write_granularity(struct request_queue *q,
380 unsigned int size)
381{
382 if (WARN_ON_ONCE(!blk_queue_is_zoned(q)))
383 return;
384
385 q->limits.zone_write_granularity = size;
386
387 if (q->limits.zone_write_granularity < q->limits.logical_block_size)
388 q->limits.zone_write_granularity = q->limits.logical_block_size;
389}
390EXPORT_SYMBOL_GPL(blk_queue_zone_write_granularity);
391
369/**392/**
370 * blk_queue_alignment_offset - set physical block alignment offset393 * blk_queue_alignment_offset - set physical block alignment offset
371 * @q: the request queue for the device394 * @q: the request queue for the device
@@ -631,6 +654,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, · 259 unmodified lines
631 t->discard_granularity;654 t->discard_granularity;
632 }655 }
633 656
657 t->zone_write_granularity = max(t->zone_write_granularity,
658 b->zone_write_granularity);
634 t->zoned = max(t->zoned, b->zoned);659 t->zoned = max(t->zoned, b->zoned);
635 return ret;660 return ret;
636}661}
@@ -847,6 +872,8 @@ EXPORT_SYMBOL_GPL(blk_queue_can_use_dma_map_merging); · 210 unmodified lines
847 */872 */
848void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)873void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
849{874{
875 struct request_queue *q = disk->queue;
876
850 switch (model) {877 switch (model) {
851 case BLK_ZONED_HM:878 case BLK_ZONED_HM:
852 /*879 /*
@@ -875,7 +902,15 @@ void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model) · 22 unmodified lines
875 break;902 break;
876 }903 }
877 904
878 disk->queue->limits.zoned = model;905 q->limits.zoned = model;
906 if (model != BLK_ZONED_NONE) {
907 /*
908 * Set the zone write granularity to the device logical block
909 * size by default. The driver can change this value if needed.
910 */
911 blk_queue_zone_write_granularity(q,
912 queue_logical_block_size(q));
913 }
879}914}
880EXPORT_SYMBOL_GPL(blk_queue_set_zoned);915EXPORT_SYMBOL_GPL(blk_queue_set_zoned);
881 916
block/blk-sysfs.c+8−0
@@ -219,6 +219,12 @@ static ssize_t queue_write_zeroes_max_show(struct request_queue *q, char *page) · 218 unmodified lines
219 (unsigned long long)q->limits.max_write_zeroes_sectors << 9);219 (unsigned long long)q->limits.max_write_zeroes_sectors << 9);
220}220}
221 221
222static ssize_t queue_zone_write_granularity_show(struct request_queue *q,
223 char *page)
224{
225 return queue_var_show(queue_zone_write_granularity(q), page);
226}
227
222static ssize_t queue_zone_append_max_show(struct request_queue *q, char *page)228static ssize_t queue_zone_append_max_show(struct request_queue *q, char *page)
223{229{
224 unsigned long long max_sectors = q->limits.max_zone_append_sectors;230 unsigned long long max_sectors = q->limits.max_zone_append_sectors;
@@ -585,6 +591,7 @@ QUEUE_RO_ENTRY(queue_discard_zeroes_data, "discard_zeroes_data"); · 360 unmodified lines
585QUEUE_RO_ENTRY(queue_write_same_max, "write_same_max_bytes");591QUEUE_RO_ENTRY(queue_write_same_max, "write_same_max_bytes");
586QUEUE_RO_ENTRY(queue_write_zeroes_max, "write_zeroes_max_bytes");592QUEUE_RO_ENTRY(queue_write_zeroes_max, "write_zeroes_max_bytes");
587QUEUE_RO_ENTRY(queue_zone_append_max, "zone_append_max_bytes");593QUEUE_RO_ENTRY(queue_zone_append_max, "zone_append_max_bytes");
594QUEUE_RO_ENTRY(queue_zone_write_granularity, "zone_write_granularity");
588 595
589QUEUE_RO_ENTRY(queue_zoned, "zoned");596QUEUE_RO_ENTRY(queue_zoned, "zoned");
590QUEUE_RO_ENTRY(queue_nr_zones, "nr_zones");597QUEUE_RO_ENTRY(queue_nr_zones, "nr_zones");
@@ -639,6 +646,7 @@ static struct attribute *queue_attrs[] = { · 48 unmodified lines
639 &queue_write_same_max_entry.attr,646 &queue_write_same_max_entry.attr,
640 &queue_write_zeroes_max_entry.attr,647 &queue_write_zeroes_max_entry.attr,
641 &queue_zone_append_max_entry.attr,648 &queue_zone_append_max_entry.attr,
649 &queue_zone_write_granularity_entry.attr,
642 &queue_nonrot_entry.attr,650 &queue_nonrot_entry.attr,
643 &queue_zoned_entry.attr,651 &queue_zoned_entry.attr,
644 &queue_nr_zones_entry.attr,652 &queue_nr_zones_entry.attr,
drivers/scsi/sd_zbc.c+8−0
@@ -789,6 +789,14 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf) · 788 unmodified lines
789 blk_queue_max_active_zones(q, 0);789 blk_queue_max_active_zones(q, 0);
790 nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks);790 nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks);
791 791
792 /*
793 * Per ZBC and ZAC specifications, writes in sequential write required
794 * zones of host-managed devices must be aligned to the device physical
795 * block size.
796 */
797 if (blk_queue_zoned_model(q) == BLK_ZONED_HM)
798 blk_queue_zone_write_granularity(q, sdkp->physical_block_size);
799
792 /* READ16/WRITE16 is mandatory for ZBC disks */800 /* READ16/WRITE16 is mandatory for ZBC disks */
793 sdkp->device->use_16_for_rw = 1;801 sdkp->device->use_16_for_rw = 1;
794 sdkp->device->use_10_for_rw = 0;802 sdkp->device->use_10_for_rw = 0;
include/linux/blkdev.h+15−0
@@ -337,6 +337,7 @@ struct queue_limits { · 336 unmodified lines
337 unsigned int max_zone_append_sectors;337 unsigned int max_zone_append_sectors;
338 unsigned int discard_granularity;338 unsigned int discard_granularity;
339 unsigned int discard_alignment;339 unsigned int discard_alignment;
340 unsigned int zone_write_granularity;
340 341
341 unsigned short max_segments;342 unsigned short max_segments;
342 unsigned short max_integrity_segments;343 unsigned short max_integrity_segments;
@@ -1160,6 +1161,8 @@ extern void blk_queue_logical_block_size(struct request_queue *, unsigned int); · 817 unmodified lines
1160extern void blk_queue_max_zone_append_sectors(struct request_queue *q,1161extern void blk_queue_max_zone_append_sectors(struct request_queue *q,
1161 unsigned int max_zone_append_sectors);1162 unsigned int max_zone_append_sectors);
1162extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);1163extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
1164void blk_queue_zone_write_granularity(struct request_queue *q,
1165 unsigned int size);
1163extern void blk_queue_alignment_offset(struct request_queue *q,1166extern void blk_queue_alignment_offset(struct request_queue *q,
1164 unsigned int alignment);1167 unsigned int alignment);
1165void blk_queue_update_readahead(struct request_queue *q);1168void blk_queue_update_readahead(struct request_queue *q);
@@ -1473,6 +1476,18 @@ static inline int bdev_io_opt(struct block_device *bdev) · 307 unmodified lines
1473 return queue_io_opt(bdev_get_queue(bdev));1476 return queue_io_opt(bdev_get_queue(bdev));
1474}1477}
1475 1478
1479static inline unsigned int
1480queue_zone_write_granularity(const struct request_queue *q)
1481{
1482 return q->limits.zone_write_granularity;
1483}
1484
1485static inline unsigned int
1486bdev_zone_write_granularity(struct block_device *bdev)
1487{
1488 return queue_zone_write_granularity(bdev_get_queue(bdev));
1489}
1490
1476static inline int queue_alignment_offset(const struct request_queue *q)1491static inline int queue_alignment_offset(const struct request_queue *q)
1477{1492{
1478 if (q->limits.misaligned)1493 if (q->limits.misaligned)