This is definitely a heavyweight solution, and in fact the bug should
not be there in the first place. See dma_complete:
static void dma_complete(DMAAIOCB *dbs, int ret)
{
trace_dma_complete(dbs, ret, dbs->common.cb);
dma_bdrv_unmap(dbs);
if (dbs->common.cb) {
dbs->common.cb(dbs->common.opaque, ret);
}
qemu_iovec_destroy(&dbs->iov);
if (dbs->bh) {
qemu_bh_delete(dbs->bh);
dbs->bh = NULL;
}
if (!dbs->in_cancel) {
/* Requests may complete while dma_aio_cancel is in progress. In
* this case, the AIOCB should not be released because it is still
* referenced by dma_aio_cancel. */
qemu_aio_release(dbs);
}
}
Perhaps something like this?
diff --git a/dma-helpers.c b/dma-helpers.c
index 53cbe92..21b70d12 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -181,15 +181,15 @@ static void dma_aio_cancel(BlockDriverAIOCB *acb)
trace_dma_aio_cancel(dbs);
+ dbs->in_cancel = true;
if (dbs->acb) {
BlockDriverAIOCB *acb = dbs->acb;
dbs->acb = NULL;
- dbs->in_cancel = true;
bdrv_aio_cancel(acb);
- dbs->in_cancel = false;
}
dbs->common.cb = NULL;
dma_complete(dbs, 0);
+ qemu_aio_release(dbs);
}
static const AIOCBInfo dma_aiocb_info = {
.