From a638ecdb8b6a2edab62cb6ca198240df65953aca Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Fam Zheng Date: Fri, 24 Apr 2015 08:44:26 -0500 Subject: [CHANGE 06/29] block: Add bdrv_aio_cancel_async To: rhvirt-patches@redhat.com, jen@redhat.com RH-Author: Fam Zheng Message-id: <1429865088-13298-7-git-send-email-famz@redhat.com> Patchwork-id: 64907 O-Subject: [RHEL-6.7 qemu-kvm PATCH v7 06/28] block: Add bdrv_aio_cancel_async Bugzilla: 1069519 RH-Acked-by: Paolo Bonzini RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Max Reitz This is the async version of bdrv_aio_cancel, which doesn't block the caller. It guarantees that the cb is called either before returning or some time later. bdrv_aio_cancel can base on bdrv_aio_cancel_async, later we can convert all .io_cancel implementations to .io_cancel_async, and the aio_poll is the common logic. In the end, .io_cancel can be dropped. Signed-off-by: Fam Zheng Signed-off-by: Stefan Hajnoczi (cherry picked from commit 02c50efe08736116048d5fc355043080f4d5859c) Signed-off-by: Fam Zheng Downstream note: qemu_aio_wait() is used in the busy wait loop in bdrv_aio_cancel, because we don't have the new aio interface. Also we have to restart the throttled queues like in bdrv_aio_co_cancel_em. --- block.c | 24 +++++++++++++++++++++++- block.h | 1 + qemu-aio.h | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) Signed-off-by: Jeff E. Nelson --- block.c | 24 +++++++++++++++++++++++- block.h | 1 + qemu-aio.h | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/block.c b/block.c index d6deba2..0b1380c 100644 --- a/block.c +++ b/block.c @@ -3829,7 +3829,29 @@ fail: void bdrv_aio_cancel(BlockDriverAIOCB *acb) { - acb->aiocb_info->cancel(acb); + if (acb->aiocb_info->cancel) { + acb->aiocb_info->cancel(acb); + } else { + BlockDriverState *bs = acb->bs; + qemu_aio_ref(acb); + bdrv_aio_cancel_async(acb); + while (acb->refcnt > 1) { + qemu_co_queue_restart_all(&bs->throttled_reqs[0]); + qemu_co_queue_restart_all(&bs->throttled_reqs[1]); + qemu_aio_wait(); + } + qemu_aio_release(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); + } } /**************************************************************/ diff --git a/block.h b/block.h index f9d48c3..f1db2ff 100644 --- a/block.h +++ b/block.h @@ -279,6 +279,7 @@ BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque); void bdrv_aio_cancel(BlockDriverAIOCB *acb); +void bdrv_aio_cancel_async(BlockDriverAIOCB *acb); typedef struct BlockRequest { /* Fields to be filled by multiwrite caller */ diff --git a/qemu-aio.h b/qemu-aio.h index b362263..043c857 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -23,6 +23,7 @@ typedef void BlockDriverCompletionFunc(void *opaque, int ret); typedef struct AIOCBInfo { void (*cancel)(BlockDriverAIOCB *acb); + void (*cancel_async)(BlockDriverAIOCB *acb); size_t aiocb_size; } AIOCBInfo; -- 2.1.0