| From 8faeb529b2dabb9df691d614dda18910a43d05c9 Mon Sep 17 00:00:00 2001 |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| Date: Wed, 4 Jun 2014 13:34:58 +0200 |
| Subject: virtio-scsi: fix various bad behavior on aborted requests |
| |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| |
| commit 8faeb529b2dabb9df691d614dda18910a43d05c9 upstream. |
| |
| Even though the virtio-scsi spec guarantees that all requests related |
| to the TMF will have been completed by the time the TMF itself completes, |
| the request queue's callback might not have run yet. This causes requests |
| to be completed more than once, and as a result triggers a variety of |
| BUGs or oopses. |
| |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Reviewed-by: Venkatesh Srinivas <venkateshs@google.com> |
| Signed-off-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/scsi/virtio_scsi.c | 22 ++++++++++++++++++++++ |
| 1 file changed, 22 insertions(+) |
| |
| --- a/drivers/scsi/virtio_scsi.c |
| +++ b/drivers/scsi/virtio_scsi.c |
| @@ -273,6 +273,16 @@ static void virtscsi_req_done(struct vir |
| virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd); |
| }; |
| |
| +static void virtscsi_poll_requests(struct virtio_scsi *vscsi) |
| +{ |
| + int i, num_vqs; |
| + |
| + num_vqs = vscsi->num_queues; |
| + for (i = 0; i < num_vqs; i++) |
| + virtscsi_vq_done(vscsi, &vscsi->req_vqs[i], |
| + virtscsi_complete_cmd); |
| +} |
| + |
| static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf) |
| { |
| struct virtio_scsi_cmd *cmd = buf; |
| @@ -607,6 +617,18 @@ static int virtscsi_tmf(struct virtio_sc |
| cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED) |
| ret = SUCCESS; |
| |
| + /* |
| + * The spec guarantees that all requests related to the TMF have |
| + * been completed, but the callback might not have run yet if |
| + * we're using independent interrupts (e.g. MSI). Poll the |
| + * virtqueues once. |
| + * |
| + * In the abort case, sc->scsi_done will do nothing, because |
| + * the block layer must have detected a timeout and as a result |
| + * REQ_ATOM_COMPLETE has been set. |
| + */ |
| + virtscsi_poll_requests(vscsi); |
| + |
| out: |
| mempool_free(cmd, virtscsi_cmd_pool); |
| return ret; |