qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 01/18] virtio: Return error from virtqueue_map_sg


From: Fam Zheng
Subject: [Qemu-devel] [PATCH 01/18] virtio: Return error from virtqueue_map_sg
Date: Fri, 17 Apr 2015 15:59:16 +0800

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]