]> xenbits.xensource.com Git - qemu-xen-unstable.git/commitdiff
Fix DMA API when handling an immediate error from block layer (Avi Kivity)
authorIan Jackson <ian.jackson@eu.citrix.com>
Wed, 7 Oct 2009 14:49:32 +0000 (15:49 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Wed, 7 Oct 2009 14:49:32 +0000 (15:49 +0100)
The block layer may signal an immediate error on an asynchronous request
by returning NULL.  The DMA API did not handle this correctly, returning
an AIO request which would never complete (and which would crash if
cancelled).

Fix by detecting the failure and propagating it.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6893 c046a42c-6fe2-441c-8c8c-71466251a162

[ Backported from 6bbff9a0b495918309074ac60375be5f9dc868b3
  by Stefano Stabellini. ]

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
dma-helpers.c

index a76c618fdcd1f593b16790d6857541bab0f9cdec..2a1621b96331fb395c522a47725a00ab980f9877 100644 (file)
@@ -71,20 +71,26 @@ static void continue_after_map_failure(void *opaque)
     qemu_bh_schedule(dbs->bh);
 }
 
-static void dma_bdrv_cb(void *opaque, int ret)
+static void dma_bdrv_unmap(DMAAIOCB *dbs)
 {
-    DMAAIOCB *dbs = (DMAAIOCB *)opaque;
-    target_phys_addr_t cur_addr, cur_len;
-    void *mem;
     int i;
 
-    dbs->acb = NULL;
-    dbs->sector_num += dbs->iov.size / 512;
     for (i = 0; i < dbs->iov.niov; ++i) {
         cpu_physical_memory_unmap(dbs->iov.iov[i].iov_base,
                                   dbs->iov.iov[i].iov_len, !dbs->is_write,
                                   dbs->iov.iov[i].iov_len);
     }
+}
+
+void dma_bdrv_cb(void *opaque, int ret)
+{
+    DMAAIOCB *dbs = (DMAAIOCB *)opaque;
+    target_phys_addr_t cur_addr, cur_len;
+    void *mem;
+
+    dbs->acb = NULL;
+    dbs->sector_num += dbs->iov.size / 512;
+    dma_bdrv_unmap(dbs);
     qemu_iovec_reset(&dbs->iov);
 
     if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
@@ -120,6 +126,11 @@ static void dma_bdrv_cb(void *opaque, int ret)
         dbs->acb = bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov,
                                   dbs->iov.size / 512, dma_bdrv_cb, dbs);
     }
+    if (!dbs->acb) {
+        dma_bdrv_unmap(dbs);
+        qemu_iovec_destroy(&dbs->iov);
+        return;
+    }
 }
 
 static BlockDriverAIOCB *dma_bdrv_io(
@@ -139,6 +150,10 @@ static BlockDriverAIOCB *dma_bdrv_io(
     dbs->bh = NULL;
     qemu_iovec_init(&dbs->iov, sg->nsg);
     dma_bdrv_cb(dbs, 0);
+    if (!dbs->acb) {
+        qemu_aio_release(dbs);
+        return NULL;
+    }
 
 #ifdef __ia64__
     if (!is_write) {