From e110f0eee587fbfc75409e0980f25275dd8551de Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 20 Jan 2014 12:49:45 +0100 Subject: [PATCH 29/34] scsi-disk: fix VERIFY emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Paolo Bonzini Message-id: <1390222185-24969-3-git-send-email-pbonzini@redhat.com> Patchwork-id: 56834 O-Subject: [RHEL 7.0 qemu-kvm PATCH 2/2] scsi-disk: fix VERIFY emulation Bugzilla: 1035644 RH-Acked-by: Fam Zheng RH-Acked-by: Laszlo Ersek RH-Acked-by: Orit Wasserman VERIFY emulation was completely botched (and remained botched through all the refactorings). The command must be emulated both in check-medium mode (BYTCHK=00, which we implement by doing nothing) and in check-bytes mode (which we do not implement yet). Unlike WRITE AND VERIFY (which we treat simply as WRITE with FUA bit set), VERIFY cannot be handled like READ. In fact the device is _receiving_ data for VERIFY, not _sending_ it like READ. Cc: qemu-stable@nongnu.org Tested-by: Hervé Poussineau Signed-off-by: Paolo Bonzini (cherry picked from commit d97e7730816094a71cd1f19a56d7a73f77cdbf96) --- hw/scsi/scsi-disk.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) Signed-off-by: Miroslav Rezanina --- hw/scsi/scsi-disk.c | 27 ++++++++++++++++++++------- 1 files changed, 20 insertions(+), 7 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index c44f159..7653411 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1720,10 +1720,19 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req) scsi_disk_emulate_unmap(r, r->iov.iov_base); break; + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: + if (r->req.status == -1) { + scsi_check_condition(r, SENSE_CODE(INVALID_FIELD)); + } + break; + case WRITE_SAME_10: case WRITE_SAME_16: scsi_disk_emulate_write_same(r, r->iov.iov_base); break; + default: abort(); } @@ -1964,6 +1973,14 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) case UNMAP: DPRINTF("Unmap (len %lu)\n", (long)r->req.cmd.xfer); break; + case VERIFY_10: + case VERIFY_12: + case VERIFY_16: + DPRINTF("Verify (bytchk %lu)\n", (r->req.buf[1] >> 1) & 3); + if (req->cmd.buf[1] & 6) { + goto illegal_request; + } + break; case WRITE_SAME_10: case WRITE_SAME_16: DPRINTF("WRITE SAME %d (len %lu)\n", @@ -2044,10 +2061,6 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED)); return 0; } - /* fallthrough */ - case VERIFY_10: - case VERIFY_12: - case VERIFY_16: DPRINTF("Write %s(sector %" PRId64 ", count %u)\n", (command & 0xe) == 0xe ? "And Verify " : "", r->req.cmd.lba, len); @@ -2315,14 +2328,14 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = { [UNMAP] = &scsi_disk_emulate_reqops, [WRITE_SAME_10] = &scsi_disk_emulate_reqops, [WRITE_SAME_16] = &scsi_disk_emulate_reqops, + [VERIFY_10] = &scsi_disk_emulate_reqops, + [VERIFY_12] = &scsi_disk_emulate_reqops, + [VERIFY_16] = &scsi_disk_emulate_reqops, [READ_6] = &scsi_disk_dma_reqops, [READ_10] = &scsi_disk_dma_reqops, [READ_12] = &scsi_disk_dma_reqops, [READ_16] = &scsi_disk_dma_reqops, - [VERIFY_10] = &scsi_disk_dma_reqops, - [VERIFY_12] = &scsi_disk_dma_reqops, - [VERIFY_16] = &scsi_disk_dma_reqops, [WRITE_6] = &scsi_disk_dma_reqops, [WRITE_10] = &scsi_disk_dma_reqops, [WRITE_12] = &scsi_disk_dma_reqops, -- 1.7.1