thebeanogamer / rpms / qemu-kvm

Forked from rpms/qemu-kvm 5 months ago
Clone

Blame SOURCES/kvm-scsi-generic-Fix-emulated-block-limits-VPD-page.patch

586cba
From e5360c1e76fee8b8dcbcba7efbb1e36f0b48ac40 Mon Sep 17 00:00:00 2001
586cba
From: Kevin Wolf <kwolf@redhat.com>
586cba
Date: Mon, 22 Aug 2022 14:53:20 +0200
586cba
Subject: [PATCH 01/23] scsi-generic: Fix emulated block limits VPD page
586cba
586cba
RH-Author: Kevin Wolf <kwolf@redhat.com>
586cba
RH-MergeRequest: 115: scsi-generic: Fix emulated block limits VPD page
586cba
RH-Bugzilla: 2120275
586cba
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
586cba
RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
586cba
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
586cba
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
586cba
RH-Commit: [1/1] 336ba583311a80beeadd1900336056404f63211a (kmwolf/centos-qemu-kvm)
586cba
Commits 01ef8185b80 amd 24b36e9813e updated the way that the maximum
586cba
transfer length is calculated for patching block limits VPD page in an
586cba
INQUIRY response.
586cba
586cba
The same updates also need to be made for the case where the host device
586cba
does not support the block limits VPD page at all and we emulate the
586cba
whole page.
586cba
586cba
Without this fix, on host block devices a maximum transfer length of
586cba
(INT_MAX - sector_size) bytes is advertised to the guest, resulting in
586cba
I/O errors when a request that exceeds the host limits is made by the
586cba
guest. (Prior to commit 24b36e9813e, this code path would use the
586cba
max_transfer value from the host instead of INT_MAX, but still miss the
586cba
fix from 01ef8185b80 where max_transfer is also capped to max_iov
586cba
host pages, so it would be less wrong, but still wrong.)
586cba
586cba
Cc: qemu-stable@nongnu.org
586cba
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2096251
586cba
Fixes: 01ef8185b809af9d287e1a03a3f9d8ea8231118a
586cba
Fixes: 24b36e9813ec15da7db62e3b3621730710c5f020
586cba
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
586cba
Message-Id: <20220822125320.48257-1-kwolf@redhat.com>
586cba
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
586cba
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
586cba
(cherry picked from commit 51e15194b0a091e5c40aab2eb234a1d36c5c58ee)
586cba
586cba
Resolved conflict: qemu_real_host_page_size() is a getter function in
586cba
current upstream, but still just a public global variable downstream.
586cba
586cba
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
586cba
---
586cba
 hw/scsi/scsi-generic.c | 21 ++++++++++++++-------
586cba
 1 file changed, 14 insertions(+), 7 deletions(-)
586cba
586cba
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
586cba
index 0306ccc7b1..3742899839 100644
586cba
--- a/hw/scsi/scsi-generic.c
586cba
+++ b/hw/scsi/scsi-generic.c
586cba
@@ -147,6 +147,18 @@ static int execute_command(BlockBackend *blk,
586cba
     return 0;
586cba
 }
586cba
 
586cba
+static uint64_t calculate_max_transfer(SCSIDevice *s)
586cba
+{
586cba
+    uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
586cba
+    uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk);
586cba
+
586cba
+    assert(max_transfer);
586cba
+    max_transfer = MIN_NON_ZERO(max_transfer,
586cba
+                                max_iov * qemu_real_host_page_size);
586cba
+
586cba
+    return max_transfer / s->blocksize;
586cba
+}
586cba
+
586cba
 static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
586cba
 {
586cba
     uint8_t page, page_idx;
586cba
@@ -179,12 +191,7 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
586cba
         (r->req.cmd.buf[1] & 0x01)) {
586cba
         page = r->req.cmd.buf[2];
586cba
         if (page == 0xb0) {
586cba
-            uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk);
586cba
-            uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk);
586cba
-
586cba
-            assert(max_transfer);
586cba
-            max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size)
586cba
-                / s->blocksize;
586cba
+            uint64_t max_transfer = calculate_max_transfer(s);
586cba
             stl_be_p(&r->buf[8], max_transfer);
586cba
             /* Also take care of the opt xfer len. */
586cba
             stl_be_p(&r->buf[12],
586cba
@@ -230,7 +237,7 @@ static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s)
586cba
     uint8_t buf[64];
586cba
 
586cba
     SCSIBlockLimits bl = {
586cba
-        .max_io_sectors = blk_get_max_transfer(s->conf.blk) / s->blocksize
586cba
+        .max_io_sectors = calculate_max_transfer(s),
586cba
     };
586cba
 
586cba
     memset(r->buf, 0, r->buflen);
586cba
-- 
586cba
2.31.1
586cba