|
|
a83cc2 |
From 6773549977d94c504ec76aed67506ae85adff973 Mon Sep 17 00:00:00 2001
|
|
|
a83cc2 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
a83cc2 |
Date: Fri, 16 Jul 2021 16:51:33 -0400
|
|
|
a83cc2 |
Subject: [PATCH 17/43] block: add max_hw_transfer to BlockLimits
|
|
|
a83cc2 |
|
|
|
a83cc2 |
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
a83cc2 |
RH-Bugzilla: 1957194
|
|
|
a83cc2 |
|
|
|
a83cc2 |
For block host devices, I/O can happen through either the kernel file
|
|
|
a83cc2 |
descriptor I/O system calls (preadv/pwritev, io_submit, io_uring)
|
|
|
a83cc2 |
or the SCSI passthrough ioctl SG_IO.
|
|
|
a83cc2 |
|
|
|
a83cc2 |
In the latter case, the size of each transfer can be limited by the
|
|
|
a83cc2 |
HBA, while for file descriptor I/O the kernel is able to split and
|
|
|
a83cc2 |
merge I/O in smaller pieces as needed. Applying the HBA limits to
|
|
|
a83cc2 |
file descriptor I/O results in more system calls and suboptimal
|
|
|
a83cc2 |
performance, so this patch splits the max_transfer limit in two:
|
|
|
a83cc2 |
max_transfer remains valid and is used in general, while max_hw_transfer
|
|
|
a83cc2 |
is limited to the maximum hardware size. max_hw_transfer can then be
|
|
|
a83cc2 |
included by the scsi-generic driver in the block limits page, to ensure
|
|
|
a83cc2 |
that the stricter hardware limit is used.
|
|
|
a83cc2 |
|
|
|
a83cc2 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
a83cc2 |
(cherry picked from commit 24b36e9813ec15da7db62e3b3621730710c5f020)
|
|
|
a83cc2 |
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
|
a83cc2 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
a83cc2 |
---
|
|
|
a83cc2 |
block/block-backend.c | 13 +++++++++++++
|
|
|
a83cc2 |
block/file-posix.c | 2 +-
|
|
|
a83cc2 |
block/io.c | 2 ++
|
|
|
a83cc2 |
hw/scsi/scsi-generic.c | 2 +-
|
|
|
a83cc2 |
include/block/block_int.h | 7 +++++++
|
|
|
a83cc2 |
include/sysemu/block-backend.h | 1 +
|
|
|
a83cc2 |
6 files changed, 25 insertions(+), 2 deletions(-)
|
|
|
a83cc2 |
|
|
|
a83cc2 |
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
|
a83cc2 |
index 136cc602c5..b5f5b4b048 100644
|
|
|
a83cc2 |
--- a/block/block-backend.c
|
|
|
a83cc2 |
+++ b/block/block-backend.c
|
|
|
a83cc2 |
@@ -1939,6 +1939,19 @@ uint32_t blk_get_request_alignment(BlockBackend *blk)
|
|
|
a83cc2 |
return bs ? bs->bl.request_alignment : BDRV_SECTOR_SIZE;
|
|
|
a83cc2 |
}
|
|
|
a83cc2 |
|
|
|
a83cc2 |
+/* Returns the maximum hardware transfer length, in bytes; guaranteed nonzero */
|
|
|
a83cc2 |
+uint64_t blk_get_max_hw_transfer(BlockBackend *blk)
|
|
|
a83cc2 |
+{
|
|
|
a83cc2 |
+ BlockDriverState *bs = blk_bs(blk);
|
|
|
a83cc2 |
+ uint64_t max = INT_MAX;
|
|
|
a83cc2 |
+
|
|
|
a83cc2 |
+ if (bs) {
|
|
|
a83cc2 |
+ max = MIN_NON_ZERO(max, bs->bl.max_hw_transfer);
|
|
|
a83cc2 |
+ max = MIN_NON_ZERO(max, bs->bl.max_transfer);
|
|
|
a83cc2 |
+ }
|
|
|
a83cc2 |
+ return ROUND_DOWN(max, blk_get_request_alignment(blk));
|
|
|
a83cc2 |
+}
|
|
|
a83cc2 |
+
|
|
|
a83cc2 |
/* Returns the maximum transfer length, in bytes; guaranteed nonzero */
|
|
|
a83cc2 |
uint32_t blk_get_max_transfer(BlockBackend *blk)
|
|
|
a83cc2 |
{
|
|
|
a83cc2 |
diff --git a/block/file-posix.c b/block/file-posix.c
|
|
|
a83cc2 |
index 1a6c799e19..44325a635d 100644
|
|
|
a83cc2 |
--- a/block/file-posix.c
|
|
|
a83cc2 |
+++ b/block/file-posix.c
|
|
|
a83cc2 |
@@ -1258,7 +1258,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
|
|
a83cc2 |
int ret = sg_get_max_transfer_length(s->fd);
|
|
|
a83cc2 |
|
|
|
a83cc2 |
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
|
|
|
a83cc2 |
- bs->bl.max_transfer = pow2floor(ret);
|
|
|
a83cc2 |
+ bs->bl.max_hw_transfer = pow2floor(ret);
|
|
|
a83cc2 |
}
|
|
|
a83cc2 |
|
|
|
a83cc2 |
ret = sg_get_max_segments(s->fd);
|
|
|
a83cc2 |
diff --git a/block/io.c b/block/io.c
|
|
|
a83cc2 |
index ca2dca3007..a4b2e3adf1 100644
|
|
|
a83cc2 |
--- a/block/io.c
|
|
|
a83cc2 |
+++ b/block/io.c
|
|
|
a83cc2 |
@@ -126,6 +126,8 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
|
|
|
a83cc2 |
{
|
|
|
a83cc2 |
dst->opt_transfer = MAX(dst->opt_transfer, src->opt_transfer);
|
|
|
a83cc2 |
dst->max_transfer = MIN_NON_ZERO(dst->max_transfer, src->max_transfer);
|
|
|
a83cc2 |
+ dst->max_hw_transfer = MIN_NON_ZERO(dst->max_hw_transfer,
|
|
|
a83cc2 |
+ src->max_hw_transfer);
|
|
|
a83cc2 |
dst->opt_mem_alignment = MAX(dst->opt_mem_alignment,
|
|
|
a83cc2 |
src->opt_mem_alignment);
|
|
|
a83cc2 |
dst->min_mem_alignment = MAX(dst->min_mem_alignment,
|
|
|
a83cc2 |
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
|
|
|
a83cc2 |
index 82e1e2ee79..3762dce749 100644
|
|
|
a83cc2 |
--- a/hw/scsi/scsi-generic.c
|
|
|
a83cc2 |
+++ b/hw/scsi/scsi-generic.c
|
|
|
a83cc2 |
@@ -179,7 +179,7 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
|
|
a83cc2 |
(r->req.cmd.buf[1] & 0x01)) {
|
|
|
a83cc2 |
page = r->req.cmd.buf[2];
|
|
|
a83cc2 |
if (page == 0xb0) {
|
|
|
a83cc2 |
- uint32_t max_transfer = blk_get_max_transfer(s->conf.blk);
|
|
|
a83cc2 |
+ uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
|
|
|
a83cc2 |
uint32_t max_iov = blk_get_max_iov(s->conf.blk);
|
|
|
a83cc2 |
|
|
|
a83cc2 |
assert(max_transfer);
|
|
|
a83cc2 |
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
|
|
a83cc2 |
index 88e4111939..09d8630ec4 100644
|
|
|
a83cc2 |
--- a/include/block/block_int.h
|
|
|
a83cc2 |
+++ b/include/block/block_int.h
|
|
|
a83cc2 |
@@ -695,6 +695,13 @@ typedef struct BlockLimits {
|
|
|
a83cc2 |
* clamped down. */
|
|
|
a83cc2 |
uint32_t max_transfer;
|
|
|
a83cc2 |
|
|
|
a83cc2 |
+ /* Maximal hardware transfer length in bytes. Applies whenever
|
|
|
a83cc2 |
+ * transfers to the device bypass the kernel I/O scheduler, for
|
|
|
a83cc2 |
+ * example with SG_IO. If larger than max_transfer or if zero,
|
|
|
a83cc2 |
+ * blk_get_max_hw_transfer will fall back to max_transfer.
|
|
|
a83cc2 |
+ */
|
|
|
a83cc2 |
+ uint64_t max_hw_transfer;
|
|
|
a83cc2 |
+
|
|
|
a83cc2 |
/* memory alignment, in bytes so that no bounce buffer is needed */
|
|
|
a83cc2 |
size_t min_mem_alignment;
|
|
|
a83cc2 |
|
|
|
a83cc2 |
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
|
|
|
a83cc2 |
index 5423e3d9c6..9ac5f7bbd3 100644
|
|
|
a83cc2 |
--- a/include/sysemu/block-backend.h
|
|
|
a83cc2 |
+++ b/include/sysemu/block-backend.h
|
|
|
a83cc2 |
@@ -208,6 +208,7 @@ void blk_eject(BlockBackend *blk, bool eject_flag);
|
|
|
a83cc2 |
int blk_get_flags(BlockBackend *blk);
|
|
|
a83cc2 |
uint32_t blk_get_request_alignment(BlockBackend *blk);
|
|
|
a83cc2 |
uint32_t blk_get_max_transfer(BlockBackend *blk);
|
|
|
a83cc2 |
+uint64_t blk_get_max_hw_transfer(BlockBackend *blk);
|
|
|
a83cc2 |
int blk_get_max_iov(BlockBackend *blk);
|
|
|
a83cc2 |
void blk_set_guest_block_size(BlockBackend *blk, int align);
|
|
|
a83cc2 |
void *blk_try_blockalign(BlockBackend *blk, size_t size);
|
|
|
a83cc2 |
--
|
|
|
a83cc2 |
2.27.0
|
|
|
a83cc2 |
|