|
|
26ba25 |
From 3fcc45e3b9a204454910832f2c9a7fcfc28a0d07 Mon Sep 17 00:00:00 2001
|
|
|
26ba25 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
26ba25 |
Date: Thu, 20 Dec 2018 12:31:00 +0000
|
|
|
26ba25 |
Subject: [PATCH 5/8] scsi-generic: keep VPD page list sorted
|
|
|
26ba25 |
|
|
|
26ba25 |
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
26ba25 |
Message-id: <20181220123103.29579-6-pbonzini@redhat.com>
|
|
|
26ba25 |
Patchwork-id: 83714
|
|
|
26ba25 |
O-Subject: [PATCH 5/8] scsi-generic: keep VPD page list sorted
|
|
|
26ba25 |
Bugzilla: 1639957
|
|
|
26ba25 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
26ba25 |
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
26ba25 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
26ba25 |
|
|
|
26ba25 |
Block limits emulation is just placing 0xb0 as the final byte of the
|
|
|
26ba25 |
VPD pages list. However, VPD page numbers must be sorted, so change
|
|
|
26ba25 |
that to an in-place insert. Since I couldn't find any disk that triggered
|
|
|
26ba25 |
the loop more than once, this was tested by adding manually 0xb1
|
|
|
26ba25 |
at the end of the list and checking that 0xb0 was added before.
|
|
|
26ba25 |
|
|
|
26ba25 |
Reported-by: Max Reitz <mreitz@redhat.com>
|
|
|
26ba25 |
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
|
26ba25 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
26ba25 |
(cherry picked from commit 6c219fc8a112fc69b29f59ea2c7865717ff6e3e0)
|
|
|
26ba25 |
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
|
26ba25 |
---
|
|
|
26ba25 |
hw/scsi/scsi-generic.c | 19 +++++++++++++++----
|
|
|
26ba25 |
1 file changed, 15 insertions(+), 4 deletions(-)
|
|
|
26ba25 |
|
|
|
26ba25 |
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
|
|
|
26ba25 |
index 4266003..98c6a34 100644
|
|
|
26ba25 |
--- a/hw/scsi/scsi-generic.c
|
|
|
26ba25 |
+++ b/hw/scsi/scsi-generic.c
|
|
|
26ba25 |
@@ -145,7 +145,7 @@ static int execute_command(BlockBackend *blk,
|
|
|
26ba25 |
|
|
|
26ba25 |
static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
|
|
26ba25 |
{
|
|
|
26ba25 |
- uint8_t page, page_len;
|
|
|
26ba25 |
+ uint8_t page, page_idx;
|
|
|
26ba25 |
|
|
|
26ba25 |
/*
|
|
|
26ba25 |
* EVPD set to zero returns the standard INQUIRY data.
|
|
|
26ba25 |
@@ -191,10 +191,21 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
|
|
26ba25 |
*
|
|
|
26ba25 |
* This way, the guest kernel will be aware of the support
|
|
|
26ba25 |
* and will use it to proper setup the SCSI device.
|
|
|
26ba25 |
+ *
|
|
|
26ba25 |
+ * VPD page numbers must be sorted, so insert 0xb0 at the
|
|
|
26ba25 |
+ * right place with an in-place insert. After the initialization
|
|
|
26ba25 |
+ * part of the for loop is executed, the device response is
|
|
|
26ba25 |
+ * at r[0] to r[page_idx - 1].
|
|
|
26ba25 |
*/
|
|
|
26ba25 |
- page_len = r->buf[3];
|
|
|
26ba25 |
- r->buf[page_len + 4] = 0xb0;
|
|
|
26ba25 |
- r->buf[3] = ++page_len;
|
|
|
26ba25 |
+ for (page_idx = lduw_be_p(r->buf + 2) + 4;
|
|
|
26ba25 |
+ page_idx > 4 && r->buf[page_idx - 1] >= 0xb0;
|
|
|
26ba25 |
+ page_idx--) {
|
|
|
26ba25 |
+ if (page_idx < r->buflen) {
|
|
|
26ba25 |
+ r->buf[page_idx] = r->buf[page_idx - 1];
|
|
|
26ba25 |
+ }
|
|
|
26ba25 |
+ }
|
|
|
26ba25 |
+ r->buf[page_idx] = 0xb0;
|
|
|
26ba25 |
+ stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
|
|
|
26ba25 |
}
|
|
|
26ba25 |
}
|
|
|
26ba25 |
}
|
|
|
26ba25 |
--
|
|
|
26ba25 |
1.8.3.1
|
|
|
26ba25 |
|