block: force an unlimited segment size on queues with a virt boundary [Linux 5.2]

block: force an unlimited segment size on queues with a virt boundary [Linux 5.2]

This Linux kernel change "block: force an unlimited segment size on queues with a virt boundary" is included in the Linux 5.2 release. This change is authored by Christoph Hellwig <hch [at] lst.de> on Tue May 21 09:01:41 2019 +0200. The commit for this change in Linux stable tree is 09324d3 (patch).

block: force an unlimited segment size on queues with a virt boundary

We currently fail to update the front/back segment size in the bio when
deciding to allow an otherwise gappy segement to a device with a
virt boundary.  The reason why this did not cause problems is that
devices with a virt boundary fundamentally don't use segments as we
know it and thus don't care.  Make that assumption formal by forcing
an unlimited segement size in this case.

Fixes: f6970f83ef79 ("block: don't check if adjacent bvecs in one bio can be mergeable")
Signed-off-by: Christoph Hellwig <[email protected]>
Reviewed-by: Ming Lei <[email protected]>
Reviewed-by: Hannes Reinecke <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>

There are 11 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 block/blk-settings.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/block/blk-settings.c b/block/blk-settings.c
index 3facc41..2ae348c 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -310,6 +310,9 @@ void blk_queue_max_segment_size(struct request_queue *q, unsigned int max_size)
               __func__, max_size);
    }

+   /* see blk_queue_virt_boundary() for the explanation */
+   WARN_ON_ONCE(q->limits.virt_boundary_mask);
+
    q->limits.max_segment_size = max_size;
 }
 EXPORT_SYMBOL(blk_queue_max_segment_size);
@@ -742,6 +745,14 @@ void blk_queue_segment_boundary(struct request_queue *q, unsigned long mask)
 void blk_queue_virt_boundary(struct request_queue *q, unsigned long mask)
 {
    q->limits.virt_boundary_mask = mask;
+
+   /*
+    * Devices that require a virtual boundary do not support scatter/gather
+    * I/O natively, but instead require a descriptor list entry for each
+    * page (which might not be idential to the Linux PAGE_SIZE).  Because
+    * of that they are not limited by our notion of "segment size".
+    */
+   q->limits.max_segment_size = UINT_MAX;
 }
 EXPORT_SYMBOL(blk_queue_virt_boundary);

Leave a Reply

Your email address will not be published. Required fields are marked *