Blame 0001-block-introduce-max_hw_iov-for-use-in-scsi-generic.patch

Daniel P. Berrangé f54452
From cc071629539dc1f303175a7e2d4ab854c0a8b20f Mon Sep 17 00:00:00 2001
Daniel P. Berrangé f54452
From: Paolo Bonzini <pbonzini@redhat.com>
Daniel P. Berrangé f54452
Date: Thu, 23 Sep 2021 09:04:36 -0400
Daniel P. Berrangé f54452
Subject: [PATCH] block: introduce max_hw_iov for use in scsi-generic
Daniel P. Berrangé f54452
Daniel P. Berrangé f54452
Linux limits the size of iovecs to 1024 (UIO_MAXIOV in the kernel
Daniel P. Berrangé f54452
sources, IOV_MAX in POSIX).  Because of this, on some host adapters
Daniel P. Berrangé f54452
requests with many iovecs are rejected with -EINVAL by the
Daniel P. Berrangé f54452
io_submit() or readv()/writev() system calls.
Daniel P. Berrangé f54452
Daniel P. Berrangé f54452
In fact, the same limit applies to SG_IO as well.  To fix both the
Daniel P. Berrangé f54452
EINVAL and the possible performance issues from using fewer iovecs
Daniel P. Berrangé f54452
than allowed by Linux (some HBAs have max_segments as low as 128),
Daniel P. Berrangé f54452
introduce a separate entry in BlockLimits to hold the max_segments
Daniel P. Berrangé f54452
value from sysfs.  This new limit is used only for SG_IO and clamped
Daniel P. Berrangé f54452
to bs->bl.max_iov anyway, just like max_hw_transfer is clamped to
Daniel P. Berrangé f54452
bs->bl.max_transfer.
Daniel P. Berrangé f54452
Daniel P. Berrangé f54452
Reported-by: Halil Pasic <pasic@linux.ibm.com>
Daniel P. Berrangé f54452
Cc: Hanna Reitz <hreitz@redhat.com>
Daniel P. Berrangé f54452
Cc: Kevin Wolf <kwolf@redhat.com>
Daniel P. Berrangé f54452
Cc: qemu-block@nongnu.org
Daniel P. Berrangé f54452
Cc: qemu-stable@nongnu.org
Daniel P. Berrangé f54452
Fixes: 18473467d5 ("file-posix: try BLKSECTGET on block devices too, do not round to power of 2", 2021-06-25)
Daniel P. Berrangé f54452
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Daniel P. Berrangé f54452
Message-Id: <20210923130436.1187591-1-pbonzini@redhat.com>
Daniel P. Berrangé f54452
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Daniel P. Berrangé f54452
---
Daniel P. Berrangé f54452
 block/block-backend.c          | 6 ++++++
Daniel P. Berrangé f54452
 block/file-posix.c             | 2 +-
Daniel P. Berrangé f54452
 block/io.c                     | 1 +
Daniel P. Berrangé f54452
 hw/scsi/scsi-generic.c         | 2 +-
Daniel P. Berrangé f54452
 include/block/block_int.h      | 7 +++++++
Daniel P. Berrangé f54452
 include/sysemu/block-backend.h | 1 +
Daniel P. Berrangé f54452
 6 files changed, 17 insertions(+), 2 deletions(-)
Daniel P. Berrangé f54452
Daniel P. Berrangé f54452
diff --git a/block/block-backend.c b/block/block-backend.c
Daniel P. Berrangé f54452
index 6140d133e2..ba2b5ebb10 100644
Daniel P. Berrangé f54452
--- a/block/block-backend.c
Daniel P. Berrangé f54452
+++ b/block/block-backend.c
Daniel P. Berrangé f54452
@@ -1986,6 +1986,12 @@ uint32_t blk_get_max_transfer(BlockBackend *blk)
Daniel P. Berrangé f54452
     return ROUND_DOWN(max, blk_get_request_alignment(blk));
Daniel P. Berrangé f54452
 }
Daniel P. Berrangé f54452
 
Daniel P. Berrangé f54452
+int blk_get_max_hw_iov(BlockBackend *blk)
Daniel P. Berrangé f54452
+{
Daniel P. Berrangé f54452
+    return MIN_NON_ZERO(blk->root->bs->bl.max_hw_iov,
Daniel P. Berrangé f54452
+                        blk->root->bs->bl.max_iov);
Daniel P. Berrangé f54452
+}
Daniel P. Berrangé f54452
+
Daniel P. Berrangé f54452
 int blk_get_max_iov(BlockBackend *blk)
Daniel P. Berrangé f54452
 {
Daniel P. Berrangé f54452
     return blk->root->bs->bl.max_iov;
Daniel P. Berrangé f54452
diff --git a/block/file-posix.c b/block/file-posix.c
Daniel P. Berrangé f54452
index c62e42743d..53be0bdc1b 100644
Daniel P. Berrangé f54452
--- a/block/file-posix.c
Daniel P. Berrangé f54452
+++ b/block/file-posix.c
Daniel P. Berrangé f54452
@@ -1273,7 +1273,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
Daniel P. Berrangé f54452
 
Daniel P. Berrangé f54452
         ret = hdev_get_max_segments(s->fd, &st);
Daniel P. Berrangé f54452
         if (ret > 0) {
Daniel P. Berrangé f54452
-            bs->bl.max_iov = ret;
Daniel P. Berrangé f54452
+            bs->bl.max_hw_iov = ret;
Daniel P. Berrangé f54452
         }
Daniel P. Berrangé f54452
     }
Daniel P. Berrangé f54452
 }
Daniel P. Berrangé f54452
diff --git a/block/io.c b/block/io.c
Daniel P. Berrangé f54452
index 18d345a87a..bb0a254def 100644
Daniel P. Berrangé f54452
--- a/block/io.c
Daniel P. Berrangé f54452
+++ b/block/io.c
Daniel P. Berrangé f54452
@@ -136,6 +136,7 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
Daniel P. Berrangé f54452
     dst->min_mem_alignment = MAX(dst->min_mem_alignment,
Daniel P. Berrangé f54452
                                  src->min_mem_alignment);
Daniel P. Berrangé f54452
     dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov);
Daniel P. Berrangé f54452
+    dst->max_hw_iov = MIN_NON_ZERO(dst->max_hw_iov, src->max_hw_iov);
Daniel P. Berrangé f54452
 }
Daniel P. Berrangé f54452
 
Daniel P. Berrangé f54452
 typedef struct BdrvRefreshLimitsState {
Daniel P. Berrangé f54452
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
Daniel P. Berrangé f54452
index 665baf900e..0306ccc7b1 100644
Daniel P. Berrangé f54452
--- a/hw/scsi/scsi-generic.c
Daniel P. Berrangé f54452
+++ b/hw/scsi/scsi-generic.c
Daniel P. Berrangé f54452
@@ -180,7 +180,7 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
Daniel P. Berrangé f54452
         page = r->req.cmd.buf[2];
Daniel P. Berrangé f54452
         if (page == 0xb0) {
Daniel P. Berrangé f54452
             uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
Daniel P. Berrangé f54452
-            uint32_t max_iov = blk_get_max_iov(s->conf.blk);
Daniel P. Berrangé f54452
+            uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk);
Daniel P. Berrangé f54452
 
Daniel P. Berrangé f54452
             assert(max_transfer);
Daniel P. Berrangé f54452
             max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size)
Daniel P. Berrangé f54452
diff --git a/include/block/block_int.h b/include/block/block_int.h
Daniel P. Berrangé f54452
index ffe86068d4..f4c75e8ba9 100644
Daniel P. Berrangé f54452
--- a/include/block/block_int.h
Daniel P. Berrangé f54452
+++ b/include/block/block_int.h
Daniel P. Berrangé f54452
@@ -718,6 +718,13 @@ typedef struct BlockLimits {
Daniel P. Berrangé f54452
      */
Daniel P. Berrangé f54452
     uint64_t max_hw_transfer;
Daniel P. Berrangé f54452
 
Daniel P. Berrangé f54452
+    /* Maximal number of scatter/gather elements allowed by the hardware.
Daniel P. Berrangé f54452
+     * Applies whenever transfers to the device bypass the kernel I/O
Daniel P. Berrangé f54452
+     * scheduler, for example with SG_IO.  If larger than max_iov
Daniel P. Berrangé f54452
+     * or if zero, blk_get_max_hw_iov will fall back to max_iov.
Daniel P. Berrangé f54452
+     */
Daniel P. Berrangé f54452
+    int max_hw_iov;
Daniel P. Berrangé f54452
+
Daniel P. Berrangé f54452
     /* memory alignment, in bytes so that no bounce buffer is needed */
Daniel P. Berrangé f54452
     size_t min_mem_alignment;
Daniel P. Berrangé f54452
 
Daniel P. Berrangé f54452
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
Daniel P. Berrangé f54452
index 29d4fdbf63..82bae55161 100644
Daniel P. Berrangé f54452
--- a/include/sysemu/block-backend.h
Daniel P. Berrangé f54452
+++ b/include/sysemu/block-backend.h
Daniel P. Berrangé f54452
@@ -211,6 +211,7 @@ uint32_t blk_get_request_alignment(BlockBackend *blk);
Daniel P. Berrangé f54452
 uint32_t blk_get_max_transfer(BlockBackend *blk);
Daniel P. Berrangé f54452
 uint64_t blk_get_max_hw_transfer(BlockBackend *blk);
Daniel P. Berrangé f54452
 int blk_get_max_iov(BlockBackend *blk);
Daniel P. Berrangé f54452
+int blk_get_max_hw_iov(BlockBackend *blk);
Daniel P. Berrangé f54452
 void blk_set_guest_block_size(BlockBackend *blk, int align);
Daniel P. Berrangé f54452
 void *blk_try_blockalign(BlockBackend *blk, size_t size);
Daniel P. Berrangé f54452
 void *blk_blockalign(BlockBackend *blk, size_t size);
Daniel P. Berrangé f54452
-- 
Daniel P. Berrangé f54452
2.33.1
Daniel P. Berrangé f54452