From patchwork Thu Oct 22 15:54:41 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 36700 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0E98CB7BA8 for ; Fri, 23 Oct 2009 03:08:36 +1100 (EST) Received: from localhost ([127.0.0.1]:39333 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N10DJ-0007Tp-MI for incoming@patchwork.ozlabs.org; Thu, 22 Oct 2009 12:08:33 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1N101G-0001O1-BM for qemu-devel@nongnu.org; Thu, 22 Oct 2009 11:56:06 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1N1018-0001Hq-Gs for qemu-devel@nongnu.org; Thu, 22 Oct 2009 11:56:02 -0400 Received: from [199.232.76.173] (port=34382 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N1018-0001Hf-6R for qemu-devel@nongnu.org; Thu, 22 Oct 2009 11:55:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58838) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1N1017-000434-Kz for qemu-devel@nongnu.org; Thu, 22 Oct 2009 11:55:57 -0400 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n9MFtu00007891 for ; Thu, 22 Oct 2009 11:55:56 -0400 Received: from localhost.localdomain (dhcp-5-175.str.redhat.com [10.32.5.175]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n9MFtlO3003324; Thu, 22 Oct 2009 11:55:55 -0400 From: Kevin Wolf To: qemu-devel@nongnu.org Date: Thu, 22 Oct 2009 17:54:41 +0200 Message-Id: <1256226882-26434-8-git-send-email-kwolf@redhat.com> In-Reply-To: <1256226882-26434-1-git-send-email-kwolf@redhat.com> References: <1256226882-26434-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.17 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: Kevin Wolf Subject: [Qemu-devel] [PATCH 7/8] linux-aio: Honour AsyncContext X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Also for Linux AIO, don't call callbacks that don't belong to the active AsyncContext. Signed-off-by: Kevin Wolf --- linux-aio.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 72 insertions(+), 15 deletions(-) diff --git a/linux-aio.c b/linux-aio.c index 19ad36d..5e892b0 100644 --- a/linux-aio.c +++ b/linux-aio.c @@ -31,12 +31,15 @@ struct qemu_laiocb { struct iocb iocb; ssize_t ret; size_t nbytes; + int async_context_id; + QLIST_ENTRY(qemu_laiocb) node; }; struct qemu_laio_state { io_context_t ctx; int efd; int count; + QLIST_HEAD(, qemu_laiocb) completed_reqs; }; static inline ssize_t io_event_ret(struct io_event *ev) @@ -44,6 +47,69 @@ static inline ssize_t io_event_ret(struct io_event *ev) return (ssize_t)(((uint64_t)ev->res2 << 32) | ev->res); } +/* + * Completes an AIO request (calls the callback and frees the ACB). + * Be sure to be in the right AsyncContext before calling this function. + */ +static void qemu_laio_process_completion(struct qemu_laio_state *s, + struct qemu_laiocb *laiocb) +{ + int ret; + + s->count--; + + ret = laiocb->ret; + if (ret != -ECANCELED) { + if (ret == laiocb->nbytes) + ret = 0; + else if (ret >= 0) + ret = -EINVAL; + + laiocb->common.cb(laiocb->common.opaque, ret); + } + + qemu_aio_release(laiocb); +} + +/* + * Processes all queued AIO requests, i.e. requests that have return from OS + * but their callback was not called yet. Requests that cannot have their + * callback called in the current AsyncContext, remain in the queue. + * + * Returns 1 if at least one request could be completed, 0 otherwise. + */ +static int qemu_laio_process_requests(void *opaque) +{ + struct qemu_laio_state *s = opaque; + struct qemu_laiocb *laiocb, *next; + int res = 0; + + QLIST_FOREACH_SAFE (laiocb, &s->completed_reqs, node, next) { + if (laiocb->async_context_id == get_async_context_id()) { + qemu_laio_process_completion(s, laiocb); + QLIST_REMOVE(laiocb, node); + res = 1; + } + } + + return res; +} + +/* + * Puts a request in the completion queue so that its callback is called the + * next time when it's possible. If we already are in the right AsyncContext, + * the request is completed immediately instead. + */ +static void qemu_laio_enqueue_completed(struct qemu_laio_state *s, + struct qemu_laiocb* laiocb) +{ + if (laiocb->async_context_id == get_async_context_id()) { + qemu_laio_process_completion(s, laiocb); + } else { + QLIST_INSERT_HEAD(&s->completed_reqs, laiocb, node); + } +} + static void qemu_laio_completion_cb(void *opaque) { struct qemu_laio_state *s = opaque; @@ -74,19 +140,8 @@ static void qemu_laio_completion_cb(void *opaque) struct qemu_laiocb *laiocb = container_of(iocb, struct qemu_laiocb, iocb); - s->count--; - - ret = laiocb->ret = io_event_ret(&events[i]); - if (ret != -ECANCELED) { - if (ret == laiocb->nbytes) - ret = 0; - else if (ret >= 0) - ret = -EINVAL; - - laiocb->common.cb(laiocb->common.opaque, ret); - } - - qemu_aio_release(laiocb); + laiocb->ret = io_event_ret(&events[i]); + qemu_laio_enqueue_completed(s, laiocb); } } } @@ -149,6 +204,7 @@ BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, laiocb->nbytes = nb_sectors * 512; laiocb->ctx = s; laiocb->ret = -EINPROGRESS; + laiocb->async_context_id = get_async_context_id(); iocbs = &laiocb->iocb; @@ -183,6 +239,7 @@ void *laio_init(void) struct qemu_laio_state *s; s = qemu_mallocz(sizeof(*s)); + QLIST_INIT(&s->completed_reqs); s->efd = eventfd(0, 0); if (s->efd == -1) goto out_free_state; @@ -191,8 +248,8 @@ void *laio_init(void) if (io_setup(MAX_EVENTS, &s->ctx) != 0) goto out_close_efd; - qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, - NULL, qemu_laio_flush_cb, NULL, s); + qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, NULL, + qemu_laio_flush_cb, qemu_laio_process_requests, s); return s;