diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-14 08:50:45 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-14 08:50:45 -0600 |
commit | 5f580e9411a24b7decc07013edeb8abf8d5ae25c (patch) | |
tree | b5f0120fc2acc4080d09ecd903c647b4e8140bbd /hw/scsi-disk.c | |
parent | ce5e5b522e8d3b848b6445c34226b69c77c46403 (diff) | |
parent | dd72fdd06268860a24f9f3828efade547ee2e2a9 (diff) | |
download | qemu-5f580e9411a24b7decc07013edeb8abf8d5ae25c.zip qemu-5f580e9411a24b7decc07013edeb8abf8d5ae25c.tar.gz qemu-5f580e9411a24b7decc07013edeb8abf8d5ae25c.tar.bz2 |
Merge remote-tracking branch 'bonzini/scsi-next' into staging
* bonzini/scsi-next:
virtio-scsi: use dma_context_memory
dma: Define dma_context_memory and use in sysbus-ohci
megasas: Correct target/lun mapping
scsi-disk: flush cache after disabling it
megasas: do not include block_int.h
scsi: remove superfluous call to scsi_device_set_ua
virtio-scsi: factor checks for VIRTIO_SCSI_S_DRIVER_OK when reporting events
scsi: do not return short responses for emulated commands
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/scsi-disk.c')
-rw-r--r-- | hw/scsi-disk.c | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 1b0afa6..49b5686 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -652,7 +652,6 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) if (buflen > SCSI_MAX_INQUIRY_LEN) { buflen = SCSI_MAX_INQUIRY_LEN; } - memset(outbuf, 0, buflen); outbuf[0] = s->qdev.type & 0x1f; outbuf[1] = (s->features & (1 << SCSI_DISK_F_REMOVABLE)) ? 0x80 : 0; @@ -1388,6 +1387,7 @@ invalid_param_len: static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) { + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); uint8_t *p = inbuf; int cmd = r->req.cmd.buf[0]; int len = r->req.cmd.xfer; @@ -1424,6 +1424,14 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) return; } } + if (!bdrv_enable_write_cache(s->qdev.conf.bs)) { + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH); + r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r); + return; + } + scsi_req_complete(&r->req, GOOD); return; @@ -1596,24 +1604,26 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) break; } + /* + * FIXME: we shouldn't return anything bigger than 4k, but the code + * requires the buffer to be as big as req->cmd.xfer in several + * places. So, do not allow CDBs with a very large ALLOCATION + * LENGTH. The real fix would be to modify scsi_read_data and + * dma_buf_read, so that they return data beyond the buflen + * as all zeros. + */ + if (req->cmd.xfer > 65536) { + goto illegal_request; + } + r->buflen = MAX(4096, req->cmd.xfer); + if (!r->iov.iov_base) { - /* - * FIXME: we shouldn't return anything bigger than 4k, but the code - * requires the buffer to be as big as req->cmd.xfer in several - * places. So, do not allow CDBs with a very large ALLOCATION - * LENGTH. The real fix would be to modify scsi_read_data and - * dma_buf_read, so that they return data beyond the buflen - * as all zeros. - */ - if (req->cmd.xfer > 65536) { - goto illegal_request; - } - r->buflen = MAX(4096, req->cmd.xfer); r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen); } buflen = req->cmd.xfer; outbuf = r->iov.iov_base; + memset(outbuf, 0, r->buflen); switch (req->cmd.buf[0]) { case TEST_UNIT_READY: assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs)); @@ -1694,12 +1704,14 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) outbuf[5] = 0; outbuf[6] = s->qdev.blocksize >> 8; outbuf[7] = 0; - buflen = 8; break; case REQUEST_SENSE: /* Just return "NO SENSE". */ buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen, (req->cmd.buf[1] & 1) == 0); + if (buflen < 0) { + goto illegal_request; + } break; case MECHANISM_STATUS: buflen = scsi_emulate_mechanism_status(s, outbuf); @@ -1770,7 +1782,6 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) } /* Protection, exponent and lowest lba field left blank. */ - buflen = req->cmd.xfer; break; } DPRINTF("Unsupported Service Action In\n"); @@ -1827,7 +1838,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) return 0; } assert(!r->req.aiocb); - r->iov.iov_len = MIN(buflen, req->cmd.xfer); + r->iov.iov_len = MIN(r->buflen, req->cmd.xfer); if (r->iov.iov_len == 0) { scsi_req_complete(&r->req, GOOD); } @@ -1962,7 +1973,6 @@ static void scsi_disk_resize_cb(void *opaque) * direct-access devices. */ if (s->qdev.type == TYPE_DISK) { - scsi_device_set_ua(&s->qdev, SENSE_CODE(CAPACITY_CHANGED)); scsi_device_report_change(&s->qdev, SENSE_CODE(CAPACITY_CHANGED)); } } |