Blob Blame Raw
From b3f427e4eb27091ca712f6c18e2e63a414dc4ce2 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Mon, 11 Jul 2016 05:33:37 +0200
Subject: [PATCH 4/7] scsi-generic: Merge block max xfer len in INQUIRY
 response

RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <1468215219-30793-5-git-send-email-famz@redhat.com>
Patchwork-id: 71108
O-Subject: [RHEL-7.3 qemu-kvm PATCH 4/6] scsi-generic: Merge block max xfer len in INQUIRY response
Bugzilla: 1318199
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Acked-by: John Snow <jsnow@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>

The rationale is similar to the above mode sense response interception:
this is practically the only channel to communicate restraints from
elsewhere such as host and block driver.

The scsi bus we attach onto can have a larger max xfer len than what is
accepted by the host file system (guarding between the host scsi LUN and
QEMU), in which case the SG_IO we generate would get -EINVAL.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <1464243305-10661-3-git-send-email-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 063143d5b1fde0fdcbae30bc7d6d14e76fa607d2)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>

Conflicts:
	hw/scsi/scsi-generic.c
We don't have BlockBackend in downstream, use bdrv_get_max_transfer_length()
instead.

The context is different because we don't have fa0d653b0 (scsi-generic:
identify AIO callbacks more clearly).

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 hw/scsi/scsi-generic.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 3733d2c..6b0c1fe 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -207,6 +207,17 @@ static void scsi_read_complete(void * opaque, int ret)
                    (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
             s->blocksize = ldl_be_p(&r->buf[8]);
             s->max_lba = ldq_be_p(&r->buf[0]);
+        } else if (s->type == TYPE_DISK &&
+            r->req.cmd.buf[0] == INQUIRY &&
+            r->req.cmd.buf[2] == 0xb0) {
+            uint32_t max_xfer_len = bdrv_get_max_transfer_length(s->conf.bs);
+            if (max_xfer_len) {
+                stl_be_p(&r->buf[8], max_xfer_len);
+                /* Also take care of the opt xfer len. */
+                if (ldl_be_p(&r->buf[12]) > max_xfer_len) {
+                    stl_be_p(&r->buf[12], max_xfer_len);
+                }
+            }
         }
         bdrv_set_guest_block_size(s->conf.bs, s->blocksize);
 
-- 
1.8.3.1