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