82 lines
2.3 KiB
Diff
82 lines
2.3 KiB
Diff
From eaa874771bb83df639e2937884240a6b05622e3f Mon Sep 17 00:00:00 2001
|
|
From: Avi Kivity <avi@redhat.com>
|
|
Date: Sat, 28 Mar 2009 16:11:25 +0000
|
|
Subject: [STABLE][PATCH 4/4] Fix DMA API when handling an immediate error from block layer
|
|
|
|
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>
|
|
|
|
---
|
|
dma-helpers.c | 27 +++++++++++++++++++++------
|
|
1 files changed, 21 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/dma-helpers.c b/dma-helpers.c
|
|
index 96a120c..1469e34 100644
|
|
--- a/dma-helpers.c
|
|
+++ b/dma-helpers.c
|
|
@@ -70,20 +70,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) {
|
|
@@ -119,6 +125,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(
|
|
@@ -138,6 +149,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;
|
|
+ }
|
|
return &dbs->common;
|
|
}
|
|
|
|
--
|
|
1.6.0.6
|
|
|