diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-04-19 11:46:13 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-04-19 16:15:58 +0200 |
commit | 7f64f8e2c3c5a02636c2a6b8d6e6c5f7a62b89f7 (patch) | |
tree | c80fcc7a327fc0e6655449a9d4c752b2302f00c4 /hw | |
parent | 7e8c49c56154ab5c45d4f07edf0c22728735da35 (diff) |
scsi: force unit access on VERIFY
Also DMA data from the host, to avoid that the host reports an
underrun.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/scsi-disk.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 7e6e17dfad..09c2715aec 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -185,6 +185,9 @@ static bool scsi_is_cmd_fua(SCSICommand *cmd) case WRITE_16: return (cmd->buf[1] & 8) != 0; + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: case WRITE_VERIFY_10: case WRITE_VERIFY_12: case WRITE_VERIFY_16: @@ -218,7 +221,10 @@ static void scsi_dma_complete(void *opaque, int ret) SCSIDiskReq *r = (SCSIDiskReq *)opaque; SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); - bdrv_acct_done(s->qdev.conf.bs, &r->acct); + if (r->req.aiocb != NULL) { + r->req.aiocb = NULL; + bdrv_acct_done(s->qdev.conf.bs, &r->acct); + } if (ret < 0) { if (scsi_handle_rw_error(r, -ret)) { @@ -427,6 +433,16 @@ static void scsi_write_data(SCSIRequest *req) return; } + if (r->req.cmd.buf[0] == VERIFY_10 || r->req.cmd.buf[0] == VERIFY_12 || + r->req.cmd.buf[0] == VERIFY_16) { + if (r->req.sg) { + scsi_dma_complete(r, 0); + } else { + scsi_write_complete(r, 0); + } + return; + } + if (r->req.sg) { dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE); r->req.resid -= r->req.sg->size; @@ -1350,8 +1366,6 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r) } DPRINTF("Unsupported Service Action In\n"); goto illegal_request; - case VERIFY_10: - break; default: scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE)); return -1; @@ -1435,7 +1449,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) case MECHANISM_STATUS: case SERVICE_ACTION_IN_16: case REQUEST_SENSE: - case VERIFY_10: rc = scsi_disk_emulate_command(r); if (rc < 0) { return 0; @@ -1461,6 +1474,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf) r->sector = r->req.cmd.lba * (s->qdev.blocksize / 512); r->sector_count = len * (s->qdev.blocksize / 512); break; + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: case WRITE_6: case WRITE_10: case WRITE_12: @@ -1811,6 +1827,9 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag, case READ_10: case READ_12: case READ_16: + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: case WRITE_6: case WRITE_10: case WRITE_12: |