From patchwork Fri Apr 17 07:59:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fam Zheng X-Patchwork-Id: 461969 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E549F1402D5 for ; Fri, 17 Apr 2015 18:04:21 +1000 (AEST) Received: from localhost ([::1]:40034 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yj1G7-00063u-Qx for incoming@patchwork.ozlabs.org; Fri, 17 Apr 2015 04:04:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60039) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yj1Ck-0007Wd-Ur for qemu-devel@nongnu.org; Fri, 17 Apr 2015 04:00:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yj1Cj-0001d9-Lz for qemu-devel@nongnu.org; Fri, 17 Apr 2015 04:00:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50524) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yj1Cj-0001cz-F7 for qemu-devel@nongnu.org; Fri, 17 Apr 2015 04:00:49 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t3H80jdn007477 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 17 Apr 2015 04:00:46 -0400 Received: from ad.nay.redhat.com (dhcp-14-137.nay.redhat.com [10.66.14.137]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t3H7xbeL004102; Fri, 17 Apr 2015 04:00:41 -0400 From: Fam Zheng To: qemu-devel@nongnu.org Date: Fri, 17 Apr 2015 15:59:28 +0800 Message-Id: <1429257573-7359-14-git-send-email-famz@redhat.com> In-Reply-To: <1429257573-7359-1-git-send-email-famz@redhat.com> References: <1429257573-7359-1-git-send-email-famz@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Kevin Wolf , "Michael S. Tsirkin" , "Aneesh Kumar K.V" , Stefan Hajnoczi , Amit Shah , Paolo Bonzini Subject: [Qemu-devel] [PATCH 13/18] virtio-blk: Graceful error handling of virtqueue_pop X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Fam Zheng --- hw/block/dataplane/virtio-blk.c | 9 ++++++- hw/block/virtio-blk.c | 56 ++++++++++++++++++++++++++++++++--------- include/hw/virtio/virtio-blk.h | 3 ++- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 3db139b..a094403 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -93,6 +93,8 @@ static void handle_notify(EventNotifier *e) VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane, host_notifier); VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); + VirtIODevice *vdev = VIRTIO_DEVICE(vblk); + Error *local_err = NULL; event_notifier_test_and_clear(&s->host_notifier); blk_io_plug(s->conf->conf.blk); @@ -116,7 +118,12 @@ static void handle_notify(EventNotifier *e) req->elem.in_num, req->elem.index); - virtio_blk_handle_request(req, &mrb); + virtio_blk_handle_request(req, &mrb, &local_err); + if (local_err) { + error_report_err(local_err); + virtio_device_set_needs_reset(vdev); + break; + } } if (mrb.num_reqs) { diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index c72a1a3..82a95a3 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -61,7 +61,12 @@ static void virtio_blk_complete_request(VirtIOBlockReq *req, static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status) { - req->dev->complete_request(req, status); + VirtIODevice *vdev = VIRTIO_DEVICE(req->dev); + + /* No need to notify completion if we're in error state */ + if (!virtio_device_needs_reset(vdev)) { + req->dev->complete_request(req, status); + } } static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, @@ -189,9 +194,18 @@ out: static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) { - VirtIOBlockReq *req = virtio_blk_alloc_request(s); + VirtIOBlockReq *req; + Error *local_err = NULL; - if (!virtqueue_pop(s->vq, &req->elem, &error_abort)) { + if (virtio_device_needs_reset(VIRTIO_DEVICE(s))) { + return NULL; + } + req = virtio_blk_alloc_request(s); + if (virtqueue_pop(s->vq, &req->elem, &local_err) <= 0) { + if (local_err) { + error_report("virtio-blk: %s", error_get_pretty(local_err)); + virtio_device_set_needs_reset(VIRTIO_DEVICE(s)); + } virtio_blk_free_request(req); return NULL; } @@ -478,7 +492,10 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev, return true; } -void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) +/* Handle a request. If error happened, errp will be set and the request will + * be freed. */ +void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb, + Error **errp) { uint32_t type; struct iovec *in_iov = req->elem.in_sg; @@ -487,22 +504,25 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) unsigned out_num = req->elem.out_num; if (req->elem.out_num < 1 || req->elem.in_num < 1) { - error_report("virtio-blk missing headers"); - exit(1); + error_setg(errp, "virtio-blk missing headers"); + virtio_blk_free_request(req); + return; } if (unlikely(iov_to_buf(iov, out_num, 0, &req->out, sizeof(req->out)) != sizeof(req->out))) { - error_report("virtio-blk request outhdr too short"); - exit(1); + error_setg(errp, "virtio-blk request outhdr too short"); + virtio_blk_free_request(req); + return; } iov_discard_front(&iov, &out_num, sizeof(req->out)); if (in_num < 1 || in_iov[in_num - 1].iov_len < sizeof(struct virtio_blk_inhdr)) { - error_report("virtio-blk request inhdr too short"); - exit(1); + error_setg(errp, "virtio-blk request inhdr too short"); + virtio_blk_free_request(req); + return; } /* We always touch the last byte, so just see how big in_iov is. */ @@ -592,6 +612,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) VirtIOBlock *s = VIRTIO_BLK(vdev); VirtIOBlockReq *req; MultiReqBuffer mrb = {}; + Error *local_err = NULL; /* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start * dataplane here instead of waiting for .set_status(). @@ -602,7 +623,12 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) } while ((req = virtio_blk_get_request(s))) { - virtio_blk_handle_request(req, &mrb); + virtio_blk_handle_request(req, &mrb, &local_err); + if (local_err) { + virtio_device_set_needs_reset(vdev); + error_report_err(local_err); + break; + } } if (mrb.num_reqs) { @@ -615,6 +641,8 @@ static void virtio_blk_dma_restart_bh(void *opaque) VirtIOBlock *s = opaque; VirtIOBlockReq *req = s->rq; MultiReqBuffer mrb = {}; + VirtIODevice *vdev = VIRTIO_DEVICE(s); + Error *local_err = NULL; qemu_bh_delete(s->bh); s->bh = NULL; @@ -623,8 +651,12 @@ static void virtio_blk_dma_restart_bh(void *opaque) while (req) { VirtIOBlockReq *next = req->next; - virtio_blk_handle_request(req, &mrb); + virtio_blk_handle_request(req, &mrb, &local_err); req = next; + if (local_err) { + virtio_device_set_needs_reset(vdev); + break; + } } if (mrb.num_reqs) { diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index 6bf5905..1569269 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -85,7 +85,8 @@ VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s); void virtio_blk_free_request(VirtIOBlockReq *req); -void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb); +void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb, + Error **errp); void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb);