diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2021-09-23 09:04:36 -0400 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2021-10-06 10:25:55 +0200 |
commit | cc071629539dc1f303175a7e2d4ab854c0a8b20f (patch) | |
tree | 1c19a3000cdb38693fe05e0f30676dc550bf51a1 /include | |
parent | d318fc20b2ecb785bfc74bd8ad9e0da9e47d2104 (diff) | |
download | qemu-cc071629539dc1f303175a7e2d4ab854c0a8b20f.zip qemu-cc071629539dc1f303175a7e2d4ab854c0a8b20f.tar.gz qemu-cc071629539dc1f303175a7e2d4ab854c0a8b20f.tar.bz2 |
block: introduce max_hw_iov for use in scsi-generic
Linux limits the size of iovecs to 1024 (UIO_MAXIOV in the kernel
sources, IOV_MAX in POSIX). Because of this, on some host adapters
requests with many iovecs are rejected with -EINVAL by the
io_submit() or readv()/writev() system calls.
In fact, the same limit applies to SG_IO as well. To fix both the
EINVAL and the possible performance issues from using fewer iovecs
than allowed by Linux (some HBAs have max_segments as low as 128),
introduce a separate entry in BlockLimits to hold the max_segments
value from sysfs. This new limit is used only for SG_IO and clamped
to bs->bl.max_iov anyway, just like max_hw_transfer is clamped to
bs->bl.max_transfer.
Reported-by: Halil Pasic <pasic@linux.ibm.com>
Cc: Hanna Reitz <hreitz@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: qemu-block@nongnu.org
Cc: qemu-stable@nongnu.org
Fixes: 18473467d5 ("file-posix: try BLKSECTGET on block devices too, do not round to power of 2", 2021-06-25)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20210923130436.1187591-1-pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/block/block_int.h | 7 | ||||
-rw-r--r-- | include/sysemu/block-backend.h | 1 |
2 files changed, 8 insertions, 0 deletions
diff --git a/include/block/block_int.h b/include/block/block_int.h index ffe8606..f4c75e8 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -718,6 +718,13 @@ typedef struct BlockLimits { */ uint64_t max_hw_transfer; + /* Maximal number of scatter/gather elements allowed by the hardware. + * Applies whenever transfers to the device bypass the kernel I/O + * scheduler, for example with SG_IO. If larger than max_iov + * or if zero, blk_get_max_hw_iov will fall back to max_iov. + */ + int max_hw_iov; + /* memory alignment, in bytes so that no bounce buffer is needed */ size_t min_mem_alignment; diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 29d4fdb..82bae55 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -211,6 +211,7 @@ uint32_t blk_get_request_alignment(BlockBackend *blk); uint32_t blk_get_max_transfer(BlockBackend *blk); uint64_t blk_get_max_hw_transfer(BlockBackend *blk); int blk_get_max_iov(BlockBackend *blk); +int blk_get_max_hw_iov(BlockBackend *blk); void blk_set_guest_block_size(BlockBackend *blk, int align); void *blk_try_blockalign(BlockBackend *blk, size_t size); void *blk_blockalign(BlockBackend *blk, size_t size); |