From 9fcfab000b31bda63095335e041fcc12ad4a6758 Mon Sep 17 00:00:00 2001 Message-Id: <9fcfab000b31bda63095335e041fcc12ad4a6758.1346668737.git.minovotn@redhat.com> In-Reply-To: References: From: Paolo Bonzini Date: Mon, 27 Aug 2012 13:42:09 +0200 Subject: [PATCH 06/10] scsi: force unit access on VERIFY RH-Author: Paolo Bonzini Message-id: <1346074931-12083-6-git-send-email-pbonzini@redhat.com> Patchwork-id: 41329 O-Subject: [RHEL 6.4 qemu-kvm PATCH 5/7] scsi: force unit access on VERIFY Bugzilla: 808664 RH-Acked-by: Gerd Hoffmann RH-Acked-by: Markus Armbruster RH-Acked-by: Orit Wasserman Bugzilla: 808664, 805501 Also DMA data from the host, to avoid that the host reports an underrun. The innocent-looking test for aiocb != NULL is actually what fixes these two bugs. Leaving the aiocb to a non-NULL value leads to an assertion failure when rerror/werror are set to stop or enospc, and the operation is retried. scsi-disk checks that the aiocb member is NULL before filling it. I overlooked this consequence of the patch when committing it upstream, hence the innocent-looking patch subject; but it actually fixes most of the reported problems with error handling and request cancellation. Signed-off-by: Paolo Bonzini (cherry picked from commit 7f64f8e2c3c5a02636c2a6b8d6e6c5f7a62b89f7) --- hw/scsi-disk.c | 24 ++++++++++++++++++++---- 1 file modificato, 20 inserzioni(+), 4 rimozioni(-) Signed-off-by: Michal Novotny --- hw/scsi-disk.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 69e511a..876449d 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -182,6 +182,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: @@ -215,7 +218,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; @@ -1342,8 +1358,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; @@ -1427,7 +1441,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; @@ -1803,6 +1816,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: -- 1.7.11.4