From patchwork Wed Oct 31 15:30:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 195949 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9029E2C00BA for ; Thu, 1 Nov 2012 04:24:28 +1100 (EST) Received: from localhost ([::1]:34487 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTc1i-0002iN-Nn for incoming@patchwork.ozlabs.org; Wed, 31 Oct 2012 13:24:26 -0400 Received: from eggs.gnu.org ([208.118.235.92]:46534) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTaHO-0000DO-6O for qemu-devel@nongnu.org; Wed, 31 Oct 2012 11:32:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TTaHH-0005N6-GL for qemu-devel@nongnu.org; Wed, 31 Oct 2012 11:32:30 -0400 Received: from mail-pa0-f45.google.com ([209.85.220.45]:55215) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTaHH-0004oe-AL for qemu-devel@nongnu.org; Wed, 31 Oct 2012 11:32:23 -0400 Received: by mail-pa0-f45.google.com with SMTP id fb10so1006039pad.4 for ; Wed, 31 Oct 2012 08:32:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=1BlKibpkB0bQ5Q8ytH8ptRv6kqqthecUlA0KgzBqYEY=; b=ZMqKtSs87sylF0ogcgxOW/8by2uZRVq68ySsWB6ipcWbv2xJ531bYo+Vu3od0P9R9I dvN9x9k0tQsOsYy4buJ+OAEITaca2Hj3kpmmiuF3FEmEJ8wKIEBgEzdGG7/KUC6nfSpE iwAfxIjWYjWZYYprdor5zyMAyBmaphMXsk7cmY590HfYvzPc8Wp6k299nt8vdWJLOKgB nZQYn1V4TFdknWKIOxBrgOb6kC3+6U+miCGRAj/JB3TDsV4LTDkVnPCYUf2ugiSChOk9 2SZryGsIdYG2bA1qqqik6WRpqXyr5fZo8jYJXFFoXOHGvRG2gUxYCtq/NmfBoDyOe889 a44g== Received: by 10.68.197.71 with SMTP id is7mr113441974pbc.79.1351697542866; Wed, 31 Oct 2012 08:32:22 -0700 (PDT) Received: from yakj.usersys.redhat.com (93-34-169-1.ip50.fastwebnet.it. [93.34.169.1]) by mx.google.com with ESMTPS id sz6sm2445230pbc.52.2012.10.31.08.32.19 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 31 Oct 2012 08:32:21 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Wed, 31 Oct 2012 16:30:36 +0100 Message-Id: <1351697456-16107-20-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.12.1 In-Reply-To: <1351697456-16107-1-git-send-email-pbonzini@redhat.com> References: <1351697456-16107-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.220.45 Cc: aliguori@us.ibm.com, stefanha@redhat.com Subject: [Qemu-devel] [PATCH v2 19/39] aio: add I/O handlers to the AioContext interface X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org With this patch, I/O handlers (including event notifier handlers) can be attached to a single AioContext. Signed-off-by: Paolo Bonzini --- aio.c | 68 ++++++++++++++++++++++++------------------------------------- async.c | 6 ++++++ main-loop.c | 33 ++++++++++++++++++++++++++++++ qemu-aio.h | 42 +++++++++++++++++++++++++++++++------- 4 file modificati, 101 inserzioni(+), 48 rimozioni(-) diff --git a/aio.c b/aio.c index 7e3fe70..c89f1e9 100644 --- a/aio.c +++ b/aio.c @@ -18,15 +18,6 @@ #include "qemu-queue.h" #include "qemu_socket.h" -/* The list of registered AIO handlers */ -static QLIST_HEAD(, AioHandler) aio_handlers; - -/* This is a simple lock used to protect the aio_handlers list. Specifically, - * it's used to ensure that no callbacks are removed while we're walking and - * dispatching callbacks. - */ -static int walking_handlers; - struct AioHandler { int fd; @@ -38,11 +29,11 @@ struct AioHandler QLIST_ENTRY(AioHandler) node; }; -static AioHandler *find_aio_handler(int fd) +static AioHandler *find_aio_handler(AioContext *ctx, int fd) { AioHandler *node; - QLIST_FOREACH(node, &aio_handlers, node) { + QLIST_FOREACH(node, &ctx->aio_handlers, node) { if (node->fd == fd) if (!node->deleted) return node; @@ -51,21 +42,22 @@ static AioHandler *find_aio_handler(int fd) return NULL; } -void qemu_aio_set_fd_handler(int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque) +void aio_set_fd_handler(AioContext *ctx, + int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque) { AioHandler *node; - node = find_aio_handler(fd); + node = find_aio_handler(ctx, fd); /* Are we deleting the fd handler? */ if (!io_read && !io_write) { if (node) { /* If the lock is held, just mark the node as deleted */ - if (walking_handlers) + if (ctx->walking_handlers) node->deleted = 1; else { /* Otherwise, delete it for real. We can't just mark it as @@ -81,7 +73,7 @@ void qemu_aio_set_fd_handler(int fd, /* Alloc and insert if it's not already there */ node = g_malloc0(sizeof(AioHandler)); node->fd = fd; - QLIST_INSERT_HEAD(&aio_handlers, node, node); + QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); } /* Update handler with latest information */ node->io_read = io_read; @@ -89,25 +81,19 @@ void qemu_aio_set_fd_handler(int fd, node->io_flush = io_flush; node->opaque = opaque; } - - qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); -} - -void qemu_aio_set_event_notifier(EventNotifier *notifier, - EventNotifierHandler *io_read, - AioFlushEventNotifierHandler *io_flush) -{ - qemu_aio_set_fd_handler(event_notifier_get_fd(notifier), - (IOHandler *)io_read, NULL, - (AioFlushHandler *)io_flush, notifier); } -void qemu_aio_flush(void) +void aio_set_event_notifier(AioContext *ctx, + EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush) { - while (qemu_aio_wait()); + aio_set_fd_handler(ctx, event_notifier_get_fd(notifier), + (IOHandler *)io_read, NULL, + (AioFlushHandler *)io_flush, notifier); } -bool qemu_aio_wait(void) +bool aio_wait(AioContext *ctx) { AioHandler *node; fd_set rdfds, wrfds; @@ -120,18 +106,18 @@ bool qemu_aio_wait(void) * Do not call select in this case, because it is possible that the caller * does not need a complete flush (as is the case for qemu_aio_wait loops). */ - if (qemu_bh_poll()) { + if (aio_bh_poll(ctx)) { return true; } - walking_handlers++; + ctx->walking_handlers++; FD_ZERO(&rdfds); FD_ZERO(&wrfds); /* fill fd sets */ busy = false; - QLIST_FOREACH(node, &aio_handlers, node) { + QLIST_FOREACH(node, &ctx->aio_handlers, node) { /* If there aren't pending AIO operations, don't invoke callbacks. * Otherwise, if there are no AIO requests, qemu_aio_wait() would * wait indefinitely. @@ -152,7 +138,7 @@ bool qemu_aio_wait(void) } } - walking_handlers--; + ctx->walking_handlers--; /* No AIO operations? Get us out of here */ if (!busy) { @@ -166,11 +152,11 @@ bool qemu_aio_wait(void) if (ret > 0) { /* we have to walk very carefully in case * qemu_aio_set_fd_handler is called while we're walking */ - node = QLIST_FIRST(&aio_handlers); + node = QLIST_FIRST(&ctx->aio_handlers); while (node) { AioHandler *tmp; - walking_handlers++; + ctx->walking_handlers++; if (!node->deleted && FD_ISSET(node->fd, &rdfds) && @@ -186,9 +172,9 @@ bool qemu_aio_wait(void) tmp = node; node = QLIST_NEXT(node, node); - walking_handlers--; + ctx->walking_handlers--; - if (!walking_handlers && tmp->deleted) { + if (!ctx->walking_handlers && tmp->deleted) { QLIST_REMOVE(tmp, node); g_free(tmp); } diff --git a/async.c b/async.c index 189ee1b..c99db79 100644 --- a/async.c +++ b/async.c @@ -136,7 +136,13 @@ void aio_bh_update_timeout(AioContext *ctx, uint32_t *timeout) } } + AioContext *aio_context_new(void) { return g_new0(AioContext, 1); } + +void aio_flush(AioContext *ctx) +{ + while (aio_wait(ctx)); +} diff --git a/main-loop.c b/main-loop.c index 40fdbd3..8f0117e 100644 --- a/main-loop.c +++ b/main-loop.c @@ -526,3 +526,36 @@ int qemu_bh_poll(void) { return aio_bh_poll(qemu_aio_context); } + +void qemu_aio_flush(void) +{ + aio_flush(qemu_aio_context); +} + +bool qemu_aio_wait(void) +{ + return aio_wait(qemu_aio_context); +} + +void qemu_aio_set_fd_handler(int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque) +{ + aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush, + opaque); + + qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque); +} + +#ifdef CONFIG_POSIX +void qemu_aio_set_event_notifier(EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush) +{ + qemu_aio_set_fd_handler(event_notifier_get_fd(notifier), + (IOHandler *)io_read, NULL, + (AioFlushHandler *)io_flush, notifier); +} +#endif diff --git a/qemu-aio.h b/qemu-aio.h index 2ed6ad3..f8a93d8 100644 --- a/qemu-aio.h +++ b/qemu-aio.h @@ -15,6 +15,7 @@ #define QEMU_AIO_H #include "qemu-common.h" +#include "qemu-queue.h" #include "event_notifier.h" typedef struct BlockDriverAIOCB BlockDriverAIOCB; @@ -43,6 +44,15 @@ typedef void QEMUBHFunc(void *opaque); typedef void IOHandler(void *opaque); typedef struct AioContext { + /* The list of registered AIO handlers */ + QLIST_HEAD(, AioHandler) aio_handlers; + + /* This is a simple lock used to protect the aio_handlers list. + * Specifically, it's used to ensure that no callbacks are removed while + * we're walking and dispatching callbacks. + */ + int walking_handlers; + /* Anchor of the list of Bottom Halves belonging to the context */ struct QEMUBH *first_bh; @@ -121,7 +131,7 @@ void qemu_bh_delete(QEMUBH *bh); /* Flush any pending AIO operation. This function will block until all * outstanding AIO operations have been completed or cancelled. */ -void qemu_aio_flush(void); +void aio_flush(AioContext *ctx); /* Wait for a single AIO completion to occur. This function will wait * until a single AIO event has completed and it will ensure something @@ -129,7 +139,7 @@ void qemu_aio_flush(void); * result of executing I/O completion or bh callbacks. * * Return whether there is still any pending AIO operation. */ -bool qemu_aio_wait(void); +bool aio_wait(AioContext *ctx); #ifdef CONFIG_POSIX /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */ @@ -142,11 +152,12 @@ typedef int (AioFlushHandler)(void *opaque); * Code that invokes AIO completion functions should rely on this function * instead of qemu_set_fd_handler[2]. */ -void qemu_aio_set_fd_handler(int fd, - IOHandler *io_read, - IOHandler *io_write, - AioFlushHandler *io_flush, - void *opaque); +void aio_set_fd_handler(AioContext *ctx, + int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque); #endif /* Register an event notifier and associated callbacks. Behaves very similarly @@ -156,8 +167,25 @@ void qemu_aio_set_fd_handler(int fd, * Code that invokes AIO completion functions should rely on this function * instead of event_notifier_set_handler. */ +void aio_set_event_notifier(AioContext *ctx, + EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush); + +/* Functions to operate on the main QEMU AioContext. */ + +void qemu_aio_flush(void); +bool qemu_aio_wait(void); void qemu_aio_set_event_notifier(EventNotifier *notifier, EventNotifierHandler *io_read, AioFlushEventNotifierHandler *io_flush); +#ifdef CONFIG_POSIX +void qemu_aio_set_fd_handler(int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque); +#endif + #endif