From patchwork Thu May 12 14:34:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 9082221 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id F16A39F1C1 for ; Thu, 12 May 2016 14:46:51 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0C3752022D for ; Thu, 12 May 2016 14:46:51 +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 D3D9E20034 for ; Thu, 12 May 2016 14:46:49 +0000 (UTC) Received: from localhost ([::1]:57920 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b0rt2-0004Af-P3 for patchwork-qemu-devel@patchwork.kernel.org; Thu, 12 May 2016 10:46:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51293) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b0rim-0004WE-Oj for qemu-devel@nongnu.org; Thu, 12 May 2016 10:36:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b0rij-0003mz-TC for qemu-devel@nongnu.org; Thu, 12 May 2016 10:36:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53822) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b0rib-0003js-6j; Thu, 12 May 2016 10:36:01 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BBB176028; Thu, 12 May 2016 14:36:00 +0000 (UTC) Received: from noname.redhat.com (ovpn-116-37.ams2.redhat.com [10.36.116.37]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u4CEZp8i028730; Thu, 12 May 2016 10:35:59 -0400 From: Kevin Wolf To: qemu-block@nongnu.org Date: Thu, 12 May 2016 16:34:46 +0200 Message-Id: <1463063749-2201-7-git-send-email-kwolf@redhat.com> In-Reply-To: <1463063749-2201-1-git-send-email-kwolf@redhat.com> References: <1463063749-2201-1-git-send-email-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 12 May 2016 14:36:00 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 06/69] block: plug whole tree at once, introduce bdrv_io_unplugged_begin/end X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable 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 From: Paolo Bonzini Extract the handling of io_plug "depth" from linux-aio.c and let the main bdrv_drain loop do nothing but wait on I/O. Like the two newly introduced functions, bdrv_io_plug and bdrv_io_unplug now operate on all children. The visit order is now symmetrical between plug and unplug, making it possible for formats to implement plug/unplug. Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini Acked-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- block/io.c | 76 ++++++++++++++++++++++++++++++++++++----------- block/linux-aio.c | 13 ++++---- block/raw-aio.h | 2 +- block/raw-posix.c | 16 +--------- include/block/block.h | 3 +- include/block/block_int.h | 5 +++- 6 files changed, 71 insertions(+), 44 deletions(-) diff --git a/block/io.c b/block/io.c index b798040..b903270 100644 --- a/block/io.c +++ b/block/io.c @@ -253,7 +253,6 @@ static void bdrv_drain_poll(BlockDriverState *bs) while (busy) { /* Keep iterating */ - bdrv_flush_io_queue(bs); busy = bdrv_requests_pending(bs); busy |= aio_poll(bdrv_get_aio_context(bs), busy); } @@ -307,20 +306,24 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs) void coroutine_fn bdrv_co_drain(BlockDriverState *bs) { bdrv_no_throttling_begin(bs); + bdrv_io_unplugged_begin(bs); bdrv_drain_recurse(bs); bdrv_co_yield_to_drain(bs); + bdrv_io_unplugged_end(bs); bdrv_no_throttling_end(bs); } void bdrv_drain(BlockDriverState *bs) { bdrv_no_throttling_begin(bs); + bdrv_io_unplugged_begin(bs); bdrv_drain_recurse(bs); if (qemu_in_coroutine()) { bdrv_co_yield_to_drain(bs); } else { bdrv_drain_poll(bs); } + bdrv_io_unplugged_end(bs); bdrv_no_throttling_end(bs); } @@ -345,6 +348,7 @@ void bdrv_drain_all(void) block_job_pause(bs->job); } bdrv_no_throttling_begin(bs); + bdrv_io_unplugged_begin(bs); bdrv_drain_recurse(bs); aio_context_release(aio_context); @@ -369,7 +373,6 @@ void bdrv_drain_all(void) aio_context_acquire(aio_context); while ((bs = bdrv_next(bs))) { if (aio_context == bdrv_get_aio_context(bs)) { - bdrv_flush_io_queue(bs); if (bdrv_requests_pending(bs)) { busy = true; aio_poll(aio_context, busy); @@ -386,6 +389,7 @@ void bdrv_drain_all(void) AioContext *aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); + bdrv_io_unplugged_end(bs); bdrv_no_throttling_end(bs); if (bs->job) { block_job_resume(bs->job); @@ -2756,31 +2760,67 @@ void bdrv_add_before_write_notifier(BlockDriverState *bs, void bdrv_io_plug(BlockDriverState *bs) { - BlockDriver *drv = bs->drv; - if (drv && drv->bdrv_io_plug) { - drv->bdrv_io_plug(bs); - } else if (bs->file) { - bdrv_io_plug(bs->file->bs); + BdrvChild *child; + + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_plug(child->bs); + } + + if (bs->io_plugged++ == 0 && bs->io_plug_disabled == 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_plug) { + drv->bdrv_io_plug(bs); + } } } void bdrv_io_unplug(BlockDriverState *bs) { - BlockDriver *drv = bs->drv; - if (drv && drv->bdrv_io_unplug) { - drv->bdrv_io_unplug(bs); - } else if (bs->file) { - bdrv_io_unplug(bs->file->bs); + BdrvChild *child; + + assert(bs->io_plugged); + if (--bs->io_plugged == 0 && bs->io_plug_disabled == 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_unplug) { + drv->bdrv_io_unplug(bs); + } + } + + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_unplug(child->bs); } } -void bdrv_flush_io_queue(BlockDriverState *bs) +void bdrv_io_unplugged_begin(BlockDriverState *bs) { - BlockDriver *drv = bs->drv; - if (drv && drv->bdrv_flush_io_queue) { - drv->bdrv_flush_io_queue(bs); - } else if (bs->file) { - bdrv_flush_io_queue(bs->file->bs); + BdrvChild *child; + + if (bs->io_plug_disabled++ == 0 && bs->io_plugged > 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_unplug) { + drv->bdrv_io_unplug(bs); + } + } + + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_unplugged_begin(child->bs); + } +} + +void bdrv_io_unplugged_end(BlockDriverState *bs) +{ + BdrvChild *child; + + assert(bs->io_plug_disabled); + QLIST_FOREACH(child, &bs->children, next) { + bdrv_io_unplugged_end(child->bs); + } + + if (--bs->io_plug_disabled == 0 && bs->io_plugged > 0) { + BlockDriver *drv = bs->drv; + if (drv && drv->bdrv_io_plug) { + drv->bdrv_io_plug(bs); + } } } diff --git a/block/linux-aio.c b/block/linux-aio.c index 805757e..102bf92 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -220,19 +220,16 @@ void laio_io_plug(BlockDriverState *bs, void *aio_ctx) { struct qemu_laio_state *s = aio_ctx; - s->io_q.plugged++; + assert(!s->io_q.plugged); + s->io_q.plugged = 1; } -void laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug) +void laio_io_unplug(BlockDriverState *bs, void *aio_ctx) { struct qemu_laio_state *s = aio_ctx; - assert(s->io_q.plugged > 0 || !unplug); - - if (unplug && --s->io_q.plugged > 0) { - return; - } - + assert(s->io_q.plugged); + s->io_q.plugged = 0; if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) { ioq_submit(s); } diff --git a/block/raw-aio.h b/block/raw-aio.h index 811e375..0f5e35a 100644 --- a/block/raw-aio.h +++ b/block/raw-aio.h @@ -43,7 +43,7 @@ BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd, void laio_detach_aio_context(void *s, AioContext *old_context); void laio_attach_aio_context(void *s, AioContext *new_context); void laio_io_plug(BlockDriverState *bs, void *aio_ctx); -void laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug); +void laio_io_unplug(BlockDriverState *bs, void *aio_ctx); #endif #ifdef _WIN32 diff --git a/block/raw-posix.c b/block/raw-posix.c index 906d5c9..50135ad 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1345,17 +1345,7 @@ 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, true); - } -#endif -} - -static void raw_aio_flush_io_queue(BlockDriverState *bs) -{ -#ifdef CONFIG_LINUX_AIO - BDRVRawState *s = bs->opaque; - if (s->use_aio) { - laio_io_unplug(bs, s->aio_ctx, false); + laio_io_unplug(bs, s->aio_ctx); } #endif } @@ -1949,7 +1939,6 @@ BlockDriver bdrv_file = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, @@ -2398,7 +2387,6 @@ static BlockDriver bdrv_host_device = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, @@ -2528,7 +2516,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, @@ -2664,7 +2651,6 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_refresh_limits = raw_refresh_limits, .bdrv_io_plug = raw_aio_plug, .bdrv_io_unplug = raw_aio_unplug, - .bdrv_flush_io_queue = raw_aio_flush_io_queue, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, diff --git a/include/block/block.h b/include/block/block.h index 3a73137..0e8b4d1 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -520,7 +520,8 @@ int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo); void bdrv_io_plug(BlockDriverState *bs); void bdrv_io_unplug(BlockDriverState *bs); -void bdrv_flush_io_queue(BlockDriverState *bs); +void bdrv_io_unplugged_begin(BlockDriverState *bs); +void bdrv_io_unplugged_end(BlockDriverState *bs); /** * bdrv_drained_begin: diff --git a/include/block/block_int.h b/include/block/block_int.h index ed9314b..f1aabb9 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -294,7 +294,6 @@ struct BlockDriver { /* io queue for linux-aio */ void (*bdrv_io_plug)(BlockDriverState *bs); void (*bdrv_io_unplug)(BlockDriverState *bs); - void (*bdrv_flush_io_queue)(BlockDriverState *bs); /** * Try to get @bs's logical and physical block size. @@ -484,6 +483,10 @@ struct BlockDriverState { uint64_t write_threshold_offset; NotifierWithReturn write_threshold_notifier; + /* counters for nested bdrv_io_plug and bdrv_io_unplugged_begin */ + unsigned io_plugged; + unsigned io_plug_disabled; + int quiesce_counter; };