diff --git a/SOURCES/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch b/SOURCES/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch new file mode 100644 index 0000000..ed6a00d --- /dev/null +++ b/SOURCES/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch @@ -0,0 +1,96 @@ +From 2fdce42dabea90646371c4cc19bfca1db666aaea Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 22 Aug 2022 14:53:20 +0200 +Subject: [PATCH] scsi-generic: Fix emulated block limits VPD page + +RH-Author: Kevin Wolf +RH-MergeRequest: 214: scsi-generic: Fix emulated block limits VPD page +RH-Commit: [1/1] 6f980d29b849a7b5cea894aefed5f0b6502c6298 +RH-Bugzilla: 2121783 +RH-Acked-by: Hanna Reitz +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina + +Commits 01ef8185b80 amd 24b36e9813e updated the way that the maximum +transfer length is calculated for patching block limits VPD page in an +INQUIRY response. + +The same updates also need to be made for the case where the host device +does not support the block limits VPD page at all and we emulate the +whole page. + +Without this fix, on host block devices a maximum transfer length of +(INT_MAX - sector_size) bytes is advertised to the guest, resulting in +I/O errors when a request that exceeds the host limits is made by the +guest. (Prior to commit 24b36e9813e, this code path would use the +max_transfer value from the host instead of INT_MAX, but still miss the +fix from 01ef8185b80 where max_transfer is also capped to max_iov +host pages, so it would be less wrong, but still wrong.) + +Cc: qemu-stable@nongnu.org +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2096251 +Fixes: 01ef8185b809af9d287e1a03a3f9d8ea8231118a +Fixes: 24b36e9813ec15da7db62e3b3621730710c5f020 +Signed-off-by: Kevin Wolf +Message-Id: <20220822125320.48257-1-kwolf@redhat.com> +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 51e15194b0a091e5c40aab2eb234a1d36c5c58ee) + +Resolved conflict: qemu_real_host_page_size() is a getter function in +current upstream, but still just a public global variable downstream. + +Signed-off-by: Kevin Wolf +--- + hw/scsi/scsi-generic.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c +index 0306ccc7b1..3742899839 100644 +--- a/hw/scsi/scsi-generic.c ++++ b/hw/scsi/scsi-generic.c +@@ -147,6 +147,18 @@ static int execute_command(BlockBackend *blk, + return 0; + } + ++static uint64_t calculate_max_transfer(SCSIDevice *s) ++{ ++ uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk); ++ uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk); ++ ++ assert(max_transfer); ++ max_transfer = MIN_NON_ZERO(max_transfer, ++ max_iov * qemu_real_host_page_size); ++ ++ return max_transfer / s->blocksize; ++} ++ + static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len) + { + uint8_t page, page_idx; +@@ -179,12 +191,7 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len) + (r->req.cmd.buf[1] & 0x01)) { + page = r->req.cmd.buf[2]; + if (page == 0xb0) { +- uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk); +- uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk); +- +- assert(max_transfer); +- max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size) +- / s->blocksize; ++ uint64_t max_transfer = calculate_max_transfer(s); + stl_be_p(&r->buf[8], max_transfer); + /* Also take care of the opt xfer len. */ + stl_be_p(&r->buf[12], +@@ -230,7 +237,7 @@ static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s) + uint8_t buf[64]; + + SCSIBlockLimits bl = { +- .max_io_sectors = blk_get_max_transfer(s->conf.blk) / s->blocksize ++ .max_io_sectors = calculate_max_transfer(s), + }; + + memset(r->buf, 0, r->buflen); +-- +2.27.0 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index 91afbe2..af28669 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -83,7 +83,7 @@ Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 6.2.0 -Release: 11%{?rcrel}%{?dist}.5 +Release: 11%{?rcrel}%{?dist}.6 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY @@ -354,6 +354,8 @@ Patch126: kvm-QIOChannelSocket-Add-support-for-MSG_ZEROCOPY-IPV6.patch Patch127: kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch # For bz#2109570 - Stalled IO Operations in VM [rhel-8.6.0.z] Patch128: kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch +# For bz#2121783 - Wrong max_sectors_kb and Maximum transfer length on the pass-through device [rhel-8.7] [rhel-8.6.0.z] +Patch129: kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch BuildRequires: wget @@ -1523,6 +1525,11 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %changelog +* Thu Sep 01 2022 Jon Maloy - 6.2.0-11.el8_6.6 +- kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch [bz#2121783] +- Resolves: bz#2121783 + (Wrong max_sectors_kb and Maximum transfer length on the pass-through device [rhel-8.7] [rhel-8.6.0.z]) + * Mon Aug 29 2022 Jon Maloy - 6.2.0-11.el8_6.5 - kvm-linux-aio-fix-unbalanced-plugged-counter-in-laio_io_.patch [bz#2109570] - kvm-linux-aio-explain-why-max-batch-is-checked-in-laio_i.patch [bz#2109570]