diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-12-10 11:16:57 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-12-15 12:21:02 +0100 |
commit | f8e1f53334700950eb6691076d51c7d60f1c28f7 (patch) | |
tree | 360c7f4578da9105eedeead7dc6d6d225ddc3ee8 /hw | |
parent | 3c55fe2a13353b3ddf1db51c34ada23d161ee428 (diff) |
scsi-disk: provide maximum transfer length
The QEMU block layer has a limit of INT_MAX bytes per transfer.
Expose it in the block limits VPD page for both regular transfers
and WRITE SAME.
Reported-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/scsi/scsi-disk.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 2f75d7d51c..f65618d802 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -49,6 +49,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #define DEFAULT_DISCARD_GRANULARITY 4096 #define DEFAULT_MAX_UNMAP_SIZE (1 << 30) /* 1 GB */ +#define DEFAULT_MAX_IO_SIZE INT_MAX /* 2 GB - 1 block */ typedef struct SCSIDiskState SCSIDiskState; @@ -79,6 +80,7 @@ struct SCSIDiskState uint64_t port_wwn; uint16_t port_index; uint64_t max_unmap_size; + uint64_t max_io_size; QEMUBH *bh; char *version; char *serial; @@ -635,6 +637,8 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) s->qdev.conf.opt_io_size / s->qdev.blocksize; unsigned int max_unmap_sectors = s->max_unmap_size / s->qdev.blocksize; + unsigned int max_io_sectors = + s->max_io_size / s->qdev.blocksize; if (s->qdev.type == TYPE_ROM) { DPRINTF("Inquiry (EVPD[%02X] not supported for CDROM\n", @@ -651,6 +655,12 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) outbuf[6] = (min_io_size >> 8) & 0xff; outbuf[7] = min_io_size & 0xff; + /* maximum transfer length */ + outbuf[8] = (max_io_sectors >> 24) & 0xff; + outbuf[9] = (max_io_sectors >> 16) & 0xff; + outbuf[10] = (max_io_sectors >> 8) & 0xff; + outbuf[11] = max_io_sectors & 0xff; + /* optimal transfer length */ outbuf[12] = (opt_io_size >> 24) & 0xff; outbuf[13] = (opt_io_size >> 16) & 0xff; @@ -674,6 +684,17 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) outbuf[29] = (unmap_sectors >> 16) & 0xff; outbuf[30] = (unmap_sectors >> 8) & 0xff; outbuf[31] = unmap_sectors & 0xff; + + /* max write same size */ + outbuf[36] = 0; + outbuf[37] = 0; + outbuf[38] = 0; + outbuf[39] = 0; + + outbuf[40] = (max_io_sectors >> 24) & 0xff; + outbuf[41] = (max_io_sectors >> 16) & 0xff; + outbuf[42] = (max_io_sectors >> 8) & 0xff; + outbuf[43] = max_io_sectors & 0xff; break; } case 0xb2: /* thin provisioning */ @@ -2579,6 +2600,8 @@ static Property scsi_hd_properties[] = { DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, DEFAULT_MAX_UNMAP_SIZE), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), DEFINE_PROP_END_OF_LIST(), }; @@ -2625,6 +2648,8 @@ static Property scsi_cd_properties[] = { DEFINE_PROP_UINT64("wwn", SCSIDiskState, wwn, 0), DEFINE_PROP_UINT64("port_wwn", SCSIDiskState, port_wwn, 0), DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), DEFINE_PROP_END_OF_LIST(), }; @@ -2690,6 +2715,8 @@ static Property scsi_disk_properties[] = { DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, DEFAULT_MAX_UNMAP_SIZE), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), DEFINE_PROP_END_OF_LIST(), }; |