From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59687) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yj1Bm-0005aO-5c for qemu-devel@nongnu.org; Fri, 17 Apr 2015 03:59:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yj1Bl-00015F-1c for qemu-devel@nongnu.org; Fri, 17 Apr 2015 03:59:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46976) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yj1Bk-000155-Qn for qemu-devel@nongnu.org; Fri, 17 Apr 2015 03:59:48 -0400 From: Fam Zheng Date: Fri, 17 Apr 2015 15:59:16 +0800 Message-Id: <1429257573-7359-2-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> Subject: [Qemu-devel] [PATCH 01/18] virtio: Return error from virtqueue_map_sg List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , "Michael S. Tsirkin" , "Aneesh Kumar K.V" , Stefan Hajnoczi , Amit Shah , Paolo Bonzini virtqueue_map_sg calls error_report() and exit() when parameter is invalid, or when mapping failed. Lift the error check to caller, by adding errp. Also, when one of the mapping failed, previous maps are reverted for cleanness. All existing callers pass in error_abort for now. Signed-off-by: Fam Zheng --- hw/block/virtio-blk.c | 4 ++-- hw/char/virtio-serial-bus.c | 4 ++-- hw/virtio/virtio.c | 27 ++++++++++++++++++--------- include/hw/virtio/virtio.h | 3 ++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 9546fd2..f7d8528 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -822,9 +822,9 @@ static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f, s->rq = req; virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr, - req->elem.in_num, 1); + req->elem.in_num, 1, &error_abort); virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr, - req->elem.out_num, 0); + req->elem.out_num, 0, &error_abort); } return 0; diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index e336bdb..1e07858 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -703,9 +703,9 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id, qemu_get_buffer(f, (unsigned char *)&port->elem, sizeof(port->elem)); virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr, - port->elem.in_num, 1); + port->elem.in_num, 1, &error_abort); virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr, - port->elem.out_num, 1); + port->elem.out_num, 1, &error_abort); /* * Port was throttled on source machine. Let's diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 17c1260..179c412 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -432,25 +432,32 @@ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, } void virtqueue_map_sg(struct iovec *sg, hwaddr *addr, - size_t num_sg, int is_write) + size_t num_sg, int is_write, + Error **errp) { - unsigned int i; + int i; hwaddr len; if (num_sg > VIRTQUEUE_MAX_SIZE) { - error_report("virtio: map attempt out of bounds: %zd > %d", - num_sg, VIRTQUEUE_MAX_SIZE); - exit(1); + error_setg(errp, "virtio: map attempt out of bounds: %zd > %d", + num_sg, VIRTQUEUE_MAX_SIZE); + return; } for (i = 0; i < num_sg; i++) { len = sg[i].iov_len; sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write); if (sg[i].iov_base == NULL || len != sg[i].iov_len) { - error_report("virtio: error trying to map MMIO memory"); - exit(1); + goto fail; } } + return; +fail: + for ( ; i >= 0; i--) { + cpu_physical_memory_unmap(sg[i].iov_base, sg[i].iov_len, + is_write, 0); + } + error_setg(errp, "virtio: error trying to map MMIO memory"); } int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) @@ -514,8 +521,10 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) } while ((i = virtqueue_next_desc(vdev, desc_pa, i, max)) != max); /* Now map what we have collected */ - virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1); - virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0); + virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1, + &error_abort); + virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0, + &error_abort); elem->index = head; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index d95f8b6..64c10cf 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -140,7 +140,8 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len, unsigned int idx); void virtqueue_map_sg(struct iovec *sg, hwaddr *addr, - size_t num_sg, int is_write); + size_t num_sg, int is_write, + Error **errp); int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem); int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, unsigned int out_bytes); -- 1.9.3