From b0c44fdfc7f9d1656d718aa2fecac4a81f941c8c Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 7 Oct 2009 15:49:32 +0100 Subject: [PATCH] Fix DMA API when handling an immediate error from block layer (Avi Kivity) 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 Signed-off-by: Anthony Liguori 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 --- dma-helpers.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/dma-helpers.c b/dma-helpers.c index a76c618fd..2a1621b96 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -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) { -- 2.39.5