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

Showing the changes to include/linux/blkdev.h (1 of 5 files). Show all

Unified · Split

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)