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
279279 do not support zone commands, they will be treated as regular block devices
280280 and zoned will report "none".
281281
282+zone_write_granularity (RO)
283+---------------------------
284+This indicates the alignment constraint, in bytes, for write operations in
285+sequential zones of zoned block devices (devices with a zoned attributed
286+that reports "host-managed" or "host-aware"). This value is always 0 for
287+regular block devices.
288+
282289 Jens 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
6060 lim->io_opt = 0;
6161 lim->misaligned = 0;
6262 lim->zoned = BLK_ZONED_NONE;
63+ lim->zone_write_granularity = 0;
6364 }
6465 EXPORT_SYMBOL(blk_set_default_limits);
6566
@@ -366,6 +367,28 @@ void blk_queue_physical_block_size(struct request_queue *q, unsigned int size) · 300 unmodified lines
366367 }
367368 EXPORT_SYMBOL(blk_queue_physical_block_size);
368369
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+ */
379+void 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+}
390+EXPORT_SYMBOL_GPL(blk_queue_zone_write_granularity);
391+
369392 /**
370393 * blk_queue_alignment_offset - set physical block alignment offset
371394 * @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
631654 t->discard_granularity;
632655 }
633656
657+ t->zone_write_granularity = max(t->zone_write_granularity,
658+ b->zone_write_granularity);
634659 t->zoned = max(t->zoned, b->zoned);
635660 return ret;
636661 }
@@ -847,6 +872,8 @@ EXPORT_SYMBOL_GPL(blk_queue_can_use_dma_map_merging); · 210 unmodified lines
847872 */
848873 void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
849874 {
875+ struct request_queue *q = disk->queue;
876+
850877 switch (model) {
851878 case BLK_ZONED_HM:
852879 /*
@@ -875,7 +902,15 @@ void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model) · 22 unmodified lines
875902 break;
876903 }
877904
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+ }
879914 }
880915 EXPORT_SYMBOL_GPL(blk_queue_set_zoned);
881916
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
219219 (unsigned long long)q->limits.max_write_zeroes_sectors << 9);
220220 }
221221
222+static 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+
222228 static ssize_t queue_zone_append_max_show(struct request_queue *q, char *page)
223229 {
224230 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
585591 QUEUE_RO_ENTRY(queue_write_same_max, "write_same_max_bytes");
586592 QUEUE_RO_ENTRY(queue_write_zeroes_max, "write_zeroes_max_bytes");
587593 QUEUE_RO_ENTRY(queue_zone_append_max, "zone_append_max_bytes");
594+QUEUE_RO_ENTRY(queue_zone_write_granularity, "zone_write_granularity");
588595
589596 QUEUE_RO_ENTRY(queue_zoned, "zoned");
590597 QUEUE_RO_ENTRY(queue_nr_zones, "nr_zones");
@@ -639,6 +646,7 @@ static struct attribute *queue_attrs[] = { · 48 unmodified lines
639646 &queue_write_same_max_entry.attr,
640647 &queue_write_zeroes_max_entry.attr,
641648 &queue_zone_append_max_entry.attr,
649+ &queue_zone_write_granularity_entry.attr,
642650 &queue_nonrot_entry.attr,
643651 &queue_zoned_entry.attr,
644652 &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
789789 blk_queue_max_active_zones(q, 0);
790790 nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks);
791791
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+
792800 /* READ16/WRITE16 is mandatory for ZBC disks */
793801 sdkp->device->use_16_for_rw = 1;
794802 sdkp->device->use_10_for_rw = 0;
include/linux/blkdev.h+15−0
@@ -337,6 +337,7 @@ struct queue_limits { · 336 unmodified lines
337337 unsigned int max_zone_append_sectors;
338338 unsigned int discard_granularity;
339339 unsigned int discard_alignment;
340+ unsigned int zone_write_granularity;
340341
341342 unsigned short max_segments;
342343 unsigned short max_integrity_segments;
@@ -1160,6 +1161,8 @@ extern void blk_queue_logical_block_size(struct request_queue *, unsigned int); · 817 unmodified lines
11601161 extern void blk_queue_max_zone_append_sectors(struct request_queue *q,
11611162 unsigned int max_zone_append_sectors);
11621163 extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
1164+void blk_queue_zone_write_granularity(struct request_queue *q,
1165+ unsigned int size);
11631166 extern void blk_queue_alignment_offset(struct request_queue *q,
11641167 unsigned int alignment);
11651168 void 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
14731476 return queue_io_opt(bdev_get_queue(bdev));
14741477 }
14751478
1479+static inline unsigned int
1480+queue_zone_write_granularity(const struct request_queue *q)
1481+{
1482+ return q->limits.zone_write_granularity;
1483+}
1484+
1485+static inline unsigned int
1486+bdev_zone_write_granularity(struct block_device *bdev)
1487+{
1488+ return queue_zone_write_granularity(bdev_get_queue(bdev));
1489+}
1490+
14761491 static inline int queue_alignment_offset(const struct request_queue *q)
14771492 {
14781493 if (q->limits.misaligned)