History

block: introduce zoned block devices zone write locking

Components relying only on the request_queue structure for accessing block devices (e.g. I/O schedulers) have a limited knowledged of the device characteristics. In particular, the device capacity cannot be easily discovered, which for a zoned block device also result in the inability to easily know the number of zones of the device (the zone size is indicated by the chunk_sectors field of the queue limits). Introduce the nr_zones field to the request_queue structure to simplify access to this information. Also, add the bitmap seq_zone_bitmap which indicates which zones of the device are sequential zones (write preferred or write required) and the bitmap seq_zones_wlock which indicates if a zone is write locked, that is, if a write request targeting a zone was dispatched to the device. These fields are initialized by the low level block device driver (sd.c for ZBC/ZAC disks). They are not initialized by stacking drivers (device mappers) handling zoned block devices (e.g. dm-linear). Using this, I/O schedulers can introduce zone write locking to control request dispatching to a zoned block device and avoid write request reordering by limiting to at most a single write request per zone outside of the scheduler at any time. Based on previous patches from Damien Le Moal.

Christoph Hellwig committed 8 years ago

Commit 6cc77e91 parent 882d4173 files · +154 −0Browse files

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

Unified · Split

include/linux/blkdev.h+111−0
@@ -121,6 +121,8 @@ typedef __u32 __bitwise req_flags_t; · 120 unmodified lines
121121 /* Look at ->special_vec for the actual data payload instead of the
122122 bio chain. */
123123 #define RQF_SPECIAL_PAYLOAD ((__force req_flags_t)(1 << 18))
124+/* The per-zone write lock is held for this request */
125+#define RQF_ZONE_WRITE_LOCKED ((__force req_flags_t)(1 << 19))
124126
125127 /* flags that prevent us from merging requests: */
126128 #define RQF_NOMERGE_FLAGS \
@@ -546,6 +548,22 @@ struct request_queue { · 419 unmodified lines
546548
547549 struct queue_limits limits;
548550
551+ /*
552+ * Zoned block device information for request dispatch control.
553+ * nr_zones is the total number of zones of the device. This is always
554+ * 0 for regular block devices. seq_zones_bitmap is a bitmap of nr_zones
555+ * bits which indicates if a zone is conventional (bit clear) or
556+ * sequential (bit set). seq_zones_wlock is a bitmap of nr_zones
557+ * bits which indicates if a zone is write locked, that is, if a write
558+ * request targeting the zone was dispatched. All three fields are
559+ * initialized by the low level device driver (e.g. scsi/sd.c).
560+ * Stacking drivers (device mappers) may or may not initialize
561+ * these fields.
562+ */
563+ unsigned int nr_zones;
564+ unsigned long *seq_zones_bitmap;
565+ unsigned long *seq_zones_wlock;
566+
549567 /*
550568 * sg stuff
551569 */
@@ -790,6 +808,27 @@ static inline unsigned int blk_queue_zone_sectors(struct request_queue *q) · 238 unmodified lines
790808 return blk_queue_is_zoned(q) ? q->limits.chunk_sectors : 0;
791809 }
792810
811+static inline unsigned int blk_queue_nr_zones(struct request_queue *q)
812+{
813+ return q->nr_zones;
814+}
815+
816+static inline unsigned int blk_queue_zone_no(struct request_queue *q,
817+ sector_t sector)
818+{
819+ if (!blk_queue_is_zoned(q))
820+ return 0;
821+ return sector >> ilog2(q->limits.chunk_sectors);
822+}
823+
824+static inline bool blk_queue_zone_is_seq(struct request_queue *q,
825+ sector_t sector)
826+{
827+ if (!blk_queue_is_zoned(q) || !q->seq_zones_bitmap)
828+ return false;
829+ return test_bit(blk_queue_zone_no(q, sector), q->seq_zones_bitmap);
830+}
831+
793832 static inline bool rq_is_sync(struct request *rq)
794833 {
795834 return op_is_sync(rq->cmd_flags);
@@ -1029,6 +1068,16 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq) · 233 unmodified lines
10291068 return blk_rq_cur_bytes(rq) >> 9;
10301069 }
10311070
1071+static inline unsigned int blk_rq_zone_no(struct request *rq)
1072+{
1073+ return blk_queue_zone_no(rq->q, blk_rq_pos(rq));
1074+}
1075+
1076+static inline unsigned int blk_rq_zone_is_seq(struct request *rq)
1077+{
1078+ return blk_queue_zone_is_seq(rq->q, blk_rq_pos(rq));
1079+}
1080+
10321081 /*
10331082 * Some commands like WRITE SAME have a payload or data transfer size which
10341083 * is different from the size of the request. Any driver that supports such
@@ -1578,7 +1627,15 @@ static inline unsigned int bdev_zone_sectors(struct block_device *bdev) · 543 unmodified lines
15781627
15791628 if (q)
15801629 return blk_queue_zone_sectors(q);
1630+ return 0;
1631+}
15811632
1633+static inline unsigned int bdev_nr_zones(struct block_device *bdev)
1634+{
1635+ struct request_queue *q = bdev_get_queue(bdev);
1636+
1637+ if (q)
1638+ return blk_queue_nr_zones(q);
15821639 return 0;
15831640 }
15841641
@@ -1954,6 +2011,60 @@ extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int, · 369 unmodified lines
19542011 extern int bdev_read_page(struct block_device *, sector_t, struct page *);
19552012 extern int bdev_write_page(struct block_device *, sector_t, struct page *,
19562013 struct writeback_control *);
2014+
2015+#ifdef CONFIG_BLK_DEV_ZONED
2016+bool blk_req_needs_zone_write_lock(struct request *rq);
2017+void __blk_req_zone_write_lock(struct request *rq);
2018+void __blk_req_zone_write_unlock(struct request *rq);
2019+
2020+static inline void blk_req_zone_write_lock(struct request *rq)
2021+{
2022+ if (blk_req_needs_zone_write_lock(rq))
2023+ __blk_req_zone_write_lock(rq);
2024+}
2025+
2026+static inline void blk_req_zone_write_unlock(struct request *rq)
2027+{
2028+ if (rq->rq_flags & RQF_ZONE_WRITE_LOCKED)
2029+ __blk_req_zone_write_unlock(rq);
2030+}
2031+
2032+static inline bool blk_req_zone_is_write_locked(struct request *rq)
2033+{
2034+ return rq->q->seq_zones_wlock &&
2035+ test_bit(blk_rq_zone_no(rq), rq->q->seq_zones_wlock);
2036+}
2037+
2038+static inline bool blk_req_can_dispatch_to_zone(struct request *rq)
2039+{
2040+ if (!blk_req_needs_zone_write_lock(rq))
2041+ return true;
2042+ return !blk_req_zone_is_write_locked(rq);
2043+}
2044+#else
2045+static inline bool blk_req_needs_zone_write_lock(struct request *rq)
2046+{
2047+ return false;
2048+}
2049+
2050+static inline void blk_req_zone_write_lock(struct request *rq)
2051+{
2052+}
2053+
2054+static inline void blk_req_zone_write_unlock(struct request *rq)
2055+{
2056+}
2057+static inline bool blk_req_zone_is_write_locked(struct request *rq)
2058+{
2059+ return false;
2060+}
2061+
2062+static inline bool blk_req_can_dispatch_to_zone(struct request *rq)
2063+{
2064+ return true;
2065+}
2066+#endif /* CONFIG_BLK_DEV_ZONED */
2067+
19572068 #else /* CONFIG_BLOCK */
19582069
19592070 struct block_device;