Browse Source
Emulation of the block limits VPD page called back into scsi-disk.c, which however expected the request to be for a SCSIDiskState and accessed a scsi-generic device outside the bounds of its struct (namely to retrieve s->max_unmap_size and s->max_io_size). To avoid this, move the emulation code to a separate function that takes a new SCSIBlockLimits struct and marshals it into the VPD response format. Reported-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>pull/77/head
6 changed files with 104 additions and 84 deletions
@ -0,0 +1,42 @@ |
|||
#include "qemu/osdep.h" |
|||
#include "qemu/units.h" |
|||
#include "qemu/bswap.h" |
|||
#include "hw/scsi/emulation.h" |
|||
|
|||
int scsi_emulate_block_limits(uint8_t *outbuf, const SCSIBlockLimits *bl) |
|||
{ |
|||
/* required VPD size with unmap support */ |
|||
memset(outbuf, 0, 0x3c); |
|||
|
|||
outbuf[0] = bl->wsnz; /* wsnz */ |
|||
|
|||
if (bl->max_io_sectors) { |
|||
/* optimal transfer length granularity. This field and the optimal
|
|||
* transfer length can't be greater than maximum transfer length. |
|||
*/ |
|||
stw_be_p(outbuf + 2, MIN(bl->min_io_size, bl->max_io_sectors)); |
|||
|
|||
/* maximum transfer length */ |
|||
stl_be_p(outbuf + 4, bl->max_io_sectors); |
|||
|
|||
/* optimal transfer length */ |
|||
stl_be_p(outbuf + 8, MIN(bl->opt_io_size, bl->max_io_sectors)); |
|||
} else { |
|||
stw_be_p(outbuf + 2, bl->min_io_size); |
|||
stl_be_p(outbuf + 8, bl->opt_io_size); |
|||
} |
|||
|
|||
/* max unmap LBA count */ |
|||
stl_be_p(outbuf + 16, bl->max_unmap_sectors); |
|||
|
|||
/* max unmap descriptors */ |
|||
stl_be_p(outbuf + 20, bl->max_unmap_descr); |
|||
|
|||
/* optimal unmap granularity; alignment is zero */ |
|||
stl_be_p(outbuf + 24, bl->unmap_sectors); |
|||
|
|||
/* max write same size, make it the same as maximum transfer length */ |
|||
stl_be_p(outbuf + 36, bl->max_io_sectors); |
|||
|
|||
return 0x3c; |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
#ifndef HW_SCSI_EMULATION_H |
|||
#define HW_SCSI_EMULATION_H 1 |
|||
|
|||
typedef struct SCSIBlockLimits { |
|||
bool wsnz; |
|||
uint16_t min_io_size; |
|||
uint32_t max_unmap_descr; |
|||
uint32_t opt_io_size; |
|||
uint32_t max_unmap_sectors; |
|||
uint32_t unmap_sectors; |
|||
uint32_t max_io_sectors; |
|||
} SCSIBlockLimits; |
|||
|
|||
int scsi_emulate_block_limits(uint8_t *outbuf, const SCSIBlockLimits *bl); |
|||
|
|||
#endif |
|||
Loading…
Reference in new issue