From 4616a45d7824a7a54e74fcee7b0048eaff7581c7 Mon Sep 17 00:00:00 2001 Message-Id: <4616a45d7824a7a54e74fcee7b0048eaff7581c7.1346668737.git.minovotn@redhat.com> In-Reply-To: References: From: Paolo Bonzini Date: Mon, 27 Aug 2012 13:42:11 +0200 Subject: [PATCH 08/10] virtio-scsi: do not compare 32-bit QEMU tags against 64-bit virtio-scsi tags RH-Author: Paolo Bonzini Message-id: <1346074931-12083-8-git-send-email-pbonzini@redhat.com> Patchwork-id: 41331 O-Subject: [RHEL 6.4 qemu-kvm PATCH 7/7] virtio-scsi: do not compare 32-bit QEMU tags against 64-bit virtio-scsi tags Bugzilla: 808664 RH-Acked-by: Gerd Hoffmann RH-Acked-by: Markus Armbruster RH-Acked-by: Orit Wasserman Bugzilla: 808664 This patch fixes a problem in handling task management functions in virtio-scsi. The cause of the problem is a mismatch between the size of the tag in QEMU (32-bit) and virtio-scsi (64-bit). Changing the QEMU size is hard because the migration format uses 32 bits to store the tag; so just don't use the QEMU tag (virtio-scsi only uses the tag for task management functions anyway) and look up the full 64-bit tag in the hba_private field. The reproducer is a bit obscure. If you cause an I/O timeout (for example with rerror=stop and doing 'cont' on the monitor continuously without fixing the error), sooner or later the guest will try to abort the command and reissue it. At this point, QEMU will report _two_ errors instead of one when you hit 'c', because the first error has not been canceled correctly. Signed-off-by: Paolo Bonzini (cherry picked from commit 4dd7c82cdbabe54386ef31939f865469a095c9c3) --- hw/virtio-scsi.c | 10 ++++++++-- 1 file modificato, 8 inserzioni(+), 2 rimozioni(-) Signed-off-by: Michal Novotny --- hw/virtio-scsi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index c75b0db..3dc9912 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -291,11 +291,17 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) goto incorrect_lun; } QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) { - if (r->tag == req->req.tmf->tag) { + VirtIOSCSIReq *cmd_req = r->hba_private; + if (cmd_req && cmd_req->req.cmd->tag == req->req.tmf->tag) { break; } } - if (r && r->hba_private) { + if (r) { + /* + * Assert that the request has not been completed yet, we + * check for it in the loop above. + */ + assert(r->hba_private); if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) { /* "If the specified command is present in the task set, then * return a service response set to FUNCTION SUCCEEDED". -- 1.7.11.4