diff options
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 72 |
1 files changed, 36 insertions, 36 deletions
@@ -4640,7 +4640,28 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) void bdrv_aio_cancel(BlockDriverAIOCB *acb) { - acb->aiocb_info->cancel(acb); + qemu_aio_ref(acb); + bdrv_aio_cancel_async(acb); + while (acb->refcnt > 1) { + if (acb->aiocb_info->get_aio_context) { + aio_poll(acb->aiocb_info->get_aio_context(acb), true); + } else if (acb->bs) { + aio_poll(bdrv_get_aio_context(acb->bs), true); + } else { + abort(); + } + } + qemu_aio_unref(acb); +} + +/* Async version of aio cancel. The caller is not blocked if the acb implements + * cancel_async, otherwise we do nothing and let the request normally complete. + * In either case the completion callback must be called. */ +void bdrv_aio_cancel_async(BlockDriverAIOCB *acb) +{ + if (acb->aiocb_info->cancel_async) { + acb->aiocb_info->cancel_async(acb); + } } /**************************************************************/ @@ -4656,18 +4677,8 @@ typedef struct BlockDriverAIOCBSync { int is_write; } BlockDriverAIOCBSync; -static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb) -{ - BlockDriverAIOCBSync *acb = - container_of(blockacb, BlockDriverAIOCBSync, common); - qemu_bh_delete(acb->bh); - acb->bh = NULL; - qemu_aio_release(acb); -} - static const AIOCBInfo bdrv_em_aiocb_info = { .aiocb_size = sizeof(BlockDriverAIOCBSync), - .cancel = bdrv_aio_cancel_em, }; static void bdrv_aio_bh_cb(void *opaque) @@ -4681,7 +4692,7 @@ static void bdrv_aio_bh_cb(void *opaque) acb->common.cb(acb->common.opaque, acb->ret); qemu_bh_delete(acb->bh); acb->bh = NULL; - qemu_aio_release(acb); + qemu_aio_unref(acb); } static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs, @@ -4738,22 +4749,8 @@ typedef struct BlockDriverAIOCBCoroutine { QEMUBH* bh; } BlockDriverAIOCBCoroutine; -static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb) -{ - AioContext *aio_context = bdrv_get_aio_context(blockacb->bs); - BlockDriverAIOCBCoroutine *acb = - container_of(blockacb, BlockDriverAIOCBCoroutine, common); - bool done = false; - - acb->done = &done; - while (!done) { - aio_poll(aio_context, true); - } -} - static const AIOCBInfo bdrv_em_co_aiocb_info = { .aiocb_size = sizeof(BlockDriverAIOCBCoroutine), - .cancel = bdrv_aio_co_cancel_em, }; static void bdrv_co_em_bh(void *opaque) @@ -4762,12 +4759,8 @@ static void bdrv_co_em_bh(void *opaque) acb->common.cb(acb->common.opaque, acb->req.error); - if (acb->done) { - *acb->done = true; - } - qemu_bh_delete(acb->bh); - qemu_aio_release(acb); + qemu_aio_unref(acb); } /* Invoke bdrv_co_do_readv/bdrv_co_do_writev */ @@ -4806,7 +4799,6 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs, acb->req.qiov = qiov; acb->req.flags = flags; acb->is_write = is_write; - acb->done = NULL; co = qemu_coroutine_create(bdrv_co_do_rw); qemu_coroutine_enter(co, acb); @@ -4833,7 +4825,6 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs, BlockDriverAIOCBCoroutine *acb; acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque); - acb->done = NULL; co = qemu_coroutine_create(bdrv_aio_flush_co_entry); qemu_coroutine_enter(co, acb); @@ -4863,7 +4854,6 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque); acb->req.sector = sector_num; acb->req.nb_sectors = nb_sectors; - acb->done = NULL; co = qemu_coroutine_create(bdrv_aio_discard_co_entry); qemu_coroutine_enter(co, acb); @@ -4891,13 +4881,23 @@ void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs, acb->bs = bs; acb->cb = cb; acb->opaque = opaque; + acb->refcnt = 1; return acb; } -void qemu_aio_release(void *p) +void qemu_aio_ref(void *p) +{ + BlockDriverAIOCB *acb = p; + acb->refcnt++; +} + +void qemu_aio_unref(void *p) { BlockDriverAIOCB *acb = p; - g_slice_free1(acb->aiocb_info->aiocb_size, acb); + assert(acb->refcnt > 0); + if (--acb->refcnt == 0) { + g_slice_free1(acb->aiocb_info->aiocb_size, acb); + } } /**************************************************************/ |