From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46135) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V2GzY-0003fw-NA for qemu-devel@nongnu.org; Thu, 25 Jul 2013 04:33:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V2GzT-0006MN-Ly for qemu-devel@nongnu.org; Thu, 25 Jul 2013 04:33:44 -0400 Received: from sh.osrg.net ([192.16.179.4]:39913) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V2GzT-0006M0-0e for qemu-devel@nongnu.org; Thu, 25 Jul 2013 04:33:39 -0400 From: MORITA Kazutaka Date: Thu, 25 Jul 2013 17:32:04 +0900 Message-Id: <1374741125-31859-10-git-send-email-morita.kazutaka@lab.ntt.co.jp> In-Reply-To: <1374741125-31859-1-git-send-email-morita.kazutaka@lab.ntt.co.jp> References: <1374741125-31859-1-git-send-email-morita.kazutaka@lab.ntt.co.jp> Subject: [Qemu-devel] [PATCH v3 09/10] sheepdog: cancel aio requests if possible List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Kevin Wolf , Stefan Hajnoczi , qemu-devel@nongnu.org Cc: Paolo Bonzini , sheepdog@lists.wpkg.org, Liu Yuan This patch tries to cancel aio requests in pending queue and failed queue. When the sheepdog driver cannot cancel the requests, it waits for them to be completed. Signed-off-by: MORITA Kazutaka --- block/sheepdog.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index 9f3fa89..7bf882a 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -294,7 +294,8 @@ struct SheepdogAIOCB { Coroutine *coroutine; void (*aio_done_func)(SheepdogAIOCB *); - bool canceled; + bool cancelable; + bool *finished; int nr_pending; }; @@ -411,6 +412,7 @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req) { SheepdogAIOCB *acb = aio_req->aiocb; + acb->cancelable = false; QLIST_REMOVE(aio_req, aio_siblings); g_free(aio_req); @@ -419,23 +421,68 @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req) static void coroutine_fn sd_finish_aiocb(SheepdogAIOCB *acb) { - if (!acb->canceled) { - qemu_coroutine_enter(acb->coroutine, NULL); + qemu_coroutine_enter(acb->coroutine, NULL); + if (acb->finished) { + *acb->finished = true; } qemu_aio_release(acb); } +/* + * Check whether the specified acb can be canceled + * + * We can cancel aio when any request belonging to the acb is: + * - Not processed by the sheepdog server. + * - Not linked to the inflight queue. + */ +static bool sd_acb_cancelable(const SheepdogAIOCB *acb) +{ + BDRVSheepdogState *s = acb->common.bs->opaque; + AIOReq *aioreq; + + if (!acb->cancelable) { + return false; + } + + QLIST_FOREACH(aioreq, &s->inflight_aio_head, aio_siblings) { + if (aioreq->aiocb == acb) { + return false; + } + } + + return false; +} + static void sd_aio_cancel(BlockDriverAIOCB *blockacb) { SheepdogAIOCB *acb = (SheepdogAIOCB *)blockacb; + BDRVSheepdogState *s = acb->common.bs->opaque; + AIOReq *aioreq, *next; + bool finished = false; + + acb->finished = &finished; + while (!finished) { + if (sd_acb_cancelable(acb)) { + /* Remove outstanding requests from pending and failed queues. */ + QLIST_FOREACH_SAFE(aioreq, &s->pending_aio_head, aio_siblings, + next) { + if (aioreq->aiocb == acb) { + free_aio_req(s, aioreq); + } + } + QLIST_FOREACH_SAFE(aioreq, &s->failed_aio_head, aio_siblings, + next) { + if (aioreq->aiocb == acb) { + free_aio_req(s, aioreq); + } + } - /* - * Sheepdog cannot cancel the requests which are already sent to - * the servers, so we just complete the request with -EIO here. - */ - acb->ret = -EIO; - qemu_coroutine_enter(acb->coroutine, NULL); - acb->canceled = true; + assert(acb->nr_pending == 0); + sd_finish_aiocb(acb); + return; + } + qemu_aio_wait(); + } } static const AIOCBInfo sd_aiocb_info = { @@ -456,7 +503,8 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov, acb->nb_sectors = nb_sectors; acb->aio_done_func = NULL; - acb->canceled = false; + acb->cancelable = true; + acb->finished = NULL; acb->coroutine = qemu_coroutine_self(); acb->ret = 0; acb->nr_pending = 0; -- 1.8.1.3.566.gaa39828