From patchwork Thu Apr 7 16:33:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 8774791 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 55952C0553 for ; Thu, 7 Apr 2016 16:34:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 40E70201EC for ; Thu, 7 Apr 2016 16:34:13 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 24D0820155 for ; Thu, 7 Apr 2016 16:34:12 +0000 (UTC) Received: from localhost ([::1]:51288 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoCsl-0001jO-Fd for patchwork-qemu-devel@patchwork.kernel.org; Thu, 07 Apr 2016 12:34:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41344) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoCsU-0001Yz-BK for qemu-devel@nongnu.org; Thu, 07 Apr 2016 12:33:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aoCsQ-0005mN-4U for qemu-devel@nongnu.org; Thu, 07 Apr 2016 12:33:54 -0400 Received: from mail-wm0-x243.google.com ([2a00:1450:400c:c09::243]:35121) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoCsP-0005mE-RB; Thu, 07 Apr 2016 12:33:50 -0400 Received: by mail-wm0-x243.google.com with SMTP id a140so22764324wma.2; Thu, 07 Apr 2016 09:33:49 -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:in-reply-to:references; bh=TIDuSg1kqiEzWQFqQvw8DIUC1oovFK31rDHOIoSU03U=; b=sX1b73M6V4OomOazB+MKCNCltpheILYM/WHDMoK38cDCvI//CDmGXp/FVtK0EF7nIy AAqZpqeXqoA5VhFrq9MaPjQzbOcjxqqye0zDVQJuFp0hjeAhSlOWvAI596gYsXohg64m TRj3EhAenPhGkwAtTVrhkh5GfsTl5JRykWuOW66oB0LcYWQ04PxyVc7JL+iTbLq4dCVZ Nw13wbc8C9aiDU19Jd2NTSS9q9aChyaM4hkk2PHtMHWNqvBHAf5jf/6Uk+BmsleU+6iU Mskjo6NGpOk1KnsLoBAvo7EhvfJ+OOOYEPBMjKhONYFt2qFnpoIv1Zq8p8wYAYz0tIfJ OhfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=TIDuSg1kqiEzWQFqQvw8DIUC1oovFK31rDHOIoSU03U=; b=G7qcacS/XOIf0+xoGaTUfDipYczdF/qLAgSgOn0O31KE4VkYGvQi+L/JsCkhjYMi8m unXPN/42UwtpXoQB/raoQtoKdT2tDq+lVviBvnRibYTBgCxcS78FJB8UrNhqIOuIcLqp 1pHU+IZnApahk5VUPj7ZDhsX8Tk+i4Hxzn4ffnFUs0OQjNQ5AlmUEmXMhDibdxQ9f2Lu s3bdGpzy6qJGZRR5yOqque0LdNgOMamRysWZH8NmN/45YjXnCgJqhbtoWcj0I2MXMq+E 0YfpGrClIigpVdKFqo9mGAPXKpElk1ONOZfqtAlXLUzPXxMgu/t3ampQ5BCgTCMaLVfI qjxA== X-Gm-Message-State: AD7BkJL5KXYUnh/AURWIRh1N1QgAXqWu6L4zJc2ZKNaJ6Q5H2L+06tmaIALU+4s8yLgssQ== X-Received: by 10.28.183.213 with SMTP id h204mr4468123wmf.96.1460046829236; Thu, 07 Apr 2016 09:33:49 -0700 (PDT) Received: from 640k.lan (94-39-141-76.adsl-ull.clienti.tiscali.it. [94.39.141.76]) by smtp.gmail.com with ESMTPSA id hh8sm9218862wjc.42.2016.04.07.09.33.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Apr 2016 09:33:48 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 7 Apr 2016 18:33:36 +0200 Message-Id: <1460046816-102846-9-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1460046816-102846-1-git-send-email-pbonzini@redhat.com> References: <1460046816-102846-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::243 Cc: kwolf@redhat.com, berto@igalia.com, famz@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Subject: [Qemu-devel] [PATCH v4 8/8] linux-aio: share one LinuxAioState within an AioContext 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This has better performance because it executes fewer system calls and does not use a bottom half per disk. Originally proposed by Ming Lei. Signed-off-by: Paolo Bonzini Reviewed-by: Stefan Hajnoczi --- async.c | 23 +++++++ block/linux-aio.c | 3 + block/raw-posix.c | 119 +++++-------------------------------- block/raw-win32.c | 2 +- include/block/aio.h | 13 ++++ {block => include/block}/raw-aio.h | 0 6 files changed, 54 insertions(+), 106 deletions(-) rename {block => include/block}/raw-aio.h (100%) diff --git a/block/raw-aio.h b/include/block/raw-aio.h similarity index 100% rename from block/raw-aio.h rename to include/block/raw-aio.h diff --git a/async.c b/async.c index b4bf205..6caa98c 100644 --- a/async.c +++ b/async.c @@ -29,6 +29,7 @@ #include "block/thread-pool.h" #include "qemu/main-loop.h" #include "qemu/atomic.h" +#include "block/raw-aio.h" /***********************************************************/ /* bottom halves (can be seen as timers which expire ASAP) */ @@ -242,6 +243,14 @@ aio_ctx_finalize(GSource *source) qemu_bh_delete(ctx->notify_dummy_bh); thread_pool_free(ctx->thread_pool); +#ifdef CONFIG_LINUX_AIO + if (ctx->linux_aio) { + laio_detach_aio_context(ctx->linux_aio, ctx); + laio_cleanup(ctx->linux_aio); + ctx->linux_aio = NULL; + } +#endif + qemu_mutex_lock(&ctx->bh_lock); while (ctx->first_bh) { QEMUBH *next = ctx->first_bh->next; @@ -282,6 +291,17 @@ ThreadPool *aio_get_thread_pool(AioContext *ctx) return ctx->thread_pool; } +#ifdef CONFIG_LINUX_AIO +LinuxAioState *aio_get_linux_aio(AioContext *ctx) +{ + if (!ctx->linux_aio) { + ctx->linux_aio = laio_init(); + laio_attach_aio_context(ctx->linux_aio, ctx); + } + return ctx->linux_aio; +} +#endif + void aio_notify(AioContext *ctx) { /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs @@ -345,6 +365,9 @@ AioContext *aio_context_new(Error **errp) false, (EventNotifierHandler *) event_notifier_dummy_cb); +#ifdef CONFIG_LINUX_AIO + ctx->linux_aio = NULL; +#endif ctx->thread_pool = NULL; qemu_mutex_init(&ctx->bh_lock); rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx); diff --git a/block/linux-aio.c b/block/linux-aio.c index 90ec98e..b73ca14 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -47,6 +47,8 @@ typedef struct { } LaioQueue; struct LinuxAioState { + AioContext *aio_context; + io_context_t ctx; EventNotifier e; @@ -283,6 +285,7 @@ void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context) void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context) { + s->aio_context = new_context; s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s); aio_set_event_notifier(new_context, &s->e, false, qemu_laio_completion_cb); diff --git a/block/raw-posix.c b/block/raw-posix.c index 71ec463..3b052a9 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -32,7 +32,7 @@ #include "trace.h" #include "block/thread-pool.h" #include "qemu/iov.h" -#include "raw-aio.h" +#include "block/raw-aio.h" #include "qapi/util.h" #include "qapi/qmp/qstring.h" @@ -137,10 +137,6 @@ typedef struct BDRVRawState { int open_flags; size_t buf_align; -#ifdef CONFIG_LINUX_AIO - int use_aio; - LinuxAioState *aio_ctx; -#endif #ifdef CONFIG_XFS bool is_xfs:1; #endif @@ -154,9 +150,6 @@ typedef struct BDRVRawState { typedef struct BDRVRawReopenState { int fd; int open_flags; -#ifdef CONFIG_LINUX_AIO - int use_aio; -#endif } BDRVRawReopenState; static int fd_open(BlockDriverState *bs); @@ -374,58 +367,15 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags) } } -static void raw_detach_aio_context(BlockDriverState *bs) -{ #ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - - if (s->use_aio) { - laio_detach_aio_context(s->aio_ctx, bdrv_get_aio_context(bs)); - } -#endif -} - -static void raw_attach_aio_context(BlockDriverState *bs, - AioContext *new_context) +static bool raw_use_aio(int bdrv_flags) { -#ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - - if (s->use_aio) { - laio_attach_aio_context(s->aio_ctx, new_context); - } -#endif -} - -#ifdef CONFIG_LINUX_AIO -static int raw_set_aio(LinuxAioState **aio_ctx, int *use_aio, int bdrv_flags) -{ - int ret = -1; - assert(aio_ctx != NULL); - assert(use_aio != NULL); /* * Currently Linux do AIO only for files opened with O_DIRECT * specified so check NOCACHE flag too */ - if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == - (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) { - - /* if non-NULL, laio_init() has already been run */ - if (*aio_ctx == NULL) { - *aio_ctx = laio_init(); - if (!*aio_ctx) { - goto error; - } - } - *use_aio = 1; - } else { - *use_aio = 0; - } - - ret = 0; - -error: - return ret; + return (bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) == + (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO); } #endif @@ -494,13 +444,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, s->fd = fd; #ifdef CONFIG_LINUX_AIO - if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) { - qemu_close(fd); - ret = -errno; - error_setg_errno(errp, -ret, "Could not set AIO state"); - goto fail; - } - if (!s->use_aio && (bdrv_flags & BDRV_O_NATIVE_AIO)) { + if (!raw_use_aio(bdrv_flags) && (bdrv_flags & BDRV_O_NATIVE_AIO)) { error_setg(errp, "aio=native was specified, but it requires " "cache.direct=on, which was not specified."); ret = -EINVAL; @@ -566,8 +510,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } #endif - raw_attach_aio_context(bs, bdrv_get_aio_context(bs)); - ret = 0; fail: if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { @@ -608,18 +550,6 @@ static int raw_reopen_prepare(BDRVReopenState *state, state->opaque = g_new0(BDRVRawReopenState, 1); raw_s = state->opaque; -#ifdef CONFIG_LINUX_AIO - raw_s->use_aio = s->use_aio; - - /* we can use s->aio_ctx instead of a copy, because the use_aio flag is - * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio() - * won't override aio_ctx if aio_ctx is non-NULL */ - if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) { - error_setg(errp, "Could not set AIO state"); - return -1; - } -#endif - if (s->type == FTYPE_CD) { raw_s->open_flags |= O_NONBLOCK; } @@ -702,9 +632,6 @@ static void raw_reopen_commit(BDRVReopenState *state) qemu_close(s->fd); s->fd = raw_s->fd; -#ifdef CONFIG_LINUX_AIO - s->use_aio = raw_s->use_aio; -#endif g_free(state->opaque); state->opaque = NULL; @@ -1319,8 +1246,9 @@ static BlockAIOCB *raw_aio_submit(BlockDriverState *bs, if (!bdrv_qiov_is_aligned(bs, qiov)) { type |= QEMU_AIO_MISALIGNED; #ifdef CONFIG_LINUX_AIO - } else if (s->use_aio) { - return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov, + } else if (bs->open_flags & BDRV_O_NATIVE_AIO) { + LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs)); + return laio_submit(bs, aio, s->fd, sector_num, qiov, nb_sectors, cb, opaque, type); #endif } @@ -1333,9 +1261,9 @@ static BlockAIOCB *raw_aio_submit(BlockDriverState *bs, static void raw_aio_plug(BlockDriverState *bs) { #ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - if (s->use_aio) { - laio_io_plug(bs, s->aio_ctx); + if (bs->open_flags & BDRV_O_NATIVE_AIO) { + LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs)); + laio_io_plug(bs, aio); } #endif } @@ -1343,9 +1271,9 @@ static void raw_aio_plug(BlockDriverState *bs) static void raw_aio_unplug(BlockDriverState *bs) { #ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - if (s->use_aio) { - laio_io_unplug(bs, s->aio_ctx); + if (bs->open_flags & BDRV_O_NATIVE_AIO) { + LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs)); + laio_io_unplug(bs, aio); } #endif } @@ -1381,13 +1309,6 @@ static void raw_close(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; - raw_detach_aio_context(bs); - -#ifdef CONFIG_LINUX_AIO - if (s->use_aio) { - laio_cleanup(s->aio_ctx); - } -#endif if (s->fd >= 0) { qemu_close(s->fd); s->fd = -1; @@ -1946,9 +1867,6 @@ BlockDriver bdrv_file = { .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - .create_opts = &raw_create_opts, }; @@ -2396,9 +2314,6 @@ static BlockDriver bdrv_host_device = { .bdrv_probe_blocksizes = hdev_probe_blocksizes, .bdrv_probe_geometry = hdev_probe_geometry, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - /* generic scsi device */ #ifdef __linux__ .bdrv_aio_ioctl = hdev_aio_ioctl, @@ -2523,9 +2438,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - /* removable device support */ .bdrv_is_inserted = cdrom_is_inserted, .bdrv_eject = cdrom_eject, @@ -2658,9 +2570,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_get_allocated_file_size = raw_get_allocated_file_size, - .bdrv_detach_aio_context = raw_detach_aio_context, - .bdrv_attach_aio_context = raw_attach_aio_context, - /* removable device support */ .bdrv_is_inserted = cdrom_is_inserted, .bdrv_eject = cdrom_eject, diff --git a/block/raw-win32.c b/block/raw-win32.c index fd23891..ce77432 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -27,7 +27,7 @@ #include "qemu/timer.h" #include "block/block_int.h" #include "qemu/module.h" -#include "raw-aio.h" +#include "block/raw-aio.h" #include "trace.h" #include "block/thread-pool.h" #include "qemu/iov.h" diff --git a/include/block/aio.h b/include/block/aio.h index 88a64ee..afd72a7 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -47,6 +47,9 @@ typedef struct AioHandler AioHandler; typedef void QEMUBHFunc(void *opaque); typedef void IOHandler(void *opaque); +struct ThreadPool; +struct LinuxAioState; + struct AioContext { GSource source; @@ -119,6 +122,13 @@ struct AioContext { /* Thread pool for performing work and receiving completion callbacks */ struct ThreadPool *thread_pool; +#ifdef CONFIG_LINUX_AIO + /* State for native Linux AIO. Uses aio_context_acquire/release for + * locking. + */ + struct LinuxAioState *linux_aio; +#endif + /* TimerLists for calling timers - one per clock type */ QEMUTimerListGroup tlg; @@ -335,6 +345,9 @@ GSource *aio_get_g_source(AioContext *ctx); /* Return the ThreadPool bound to this AioContext */ struct ThreadPool *aio_get_thread_pool(AioContext *ctx); +/* Return the LinuxAioState bound to this AioContext */ +struct LinuxAioState *aio_get_linux_aio(AioContext *ctx); + /** * aio_timer_new: * @ctx: the aio context