Skip to content

Commit

Permalink
scsi-generic: keep VPD page list sorted
Browse files Browse the repository at this point in the history
Block limits emulation is just placing 0xb0 as the final byte of the
VPD pages list.  However, VPD page numbers must be sorted, so change
that to an in-place insert.  Since I couldn't find any disk that triggered
the loop more than once, this was tested by adding manually 0xb1
at the end of the list and checking that 0xb0 was added before.

Reported-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
bonzini committed Nov 6, 2018
1 parent e58ccf0 commit 6c219fc
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions hw/scsi/scsi-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static int execute_command(BlockBackend *blk,

static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
{
uint8_t page, page_len;
uint8_t page, page_idx;

/*
* EVPD set to zero returns the standard INQUIRY data.
Expand Down Expand Up @@ -190,10 +190,21 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
*
* This way, the guest kernel will be aware of the support
* and will use it to proper setup the SCSI device.
*
* VPD page numbers must be sorted, so insert 0xb0 at the
* right place with an in-place insert. After the initialization
* part of the for loop is executed, the device response is
* at r[0] to r[page_idx - 1].
*/
page_len = r->buf[3];
r->buf[page_len + 4] = 0xb0;
r->buf[3] = ++page_len;
for (page_idx = lduw_be_p(r->buf + 2) + 4;
page_idx > 4 && r->buf[page_idx - 1] >= 0xb0;
page_idx--) {
if (page_idx < r->buflen) {
r->buf[page_idx] = r->buf[page_idx - 1];
}
}
r->buf[page_idx] = 0xb0;
stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
}
}
}
Expand Down

0 comments on commit 6c219fc

Please sign in to comment.