From patchwork Thu Apr 7 16:33:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 8774881 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 80AE29F3D1 for ; Thu, 7 Apr 2016 16:38:00 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8106C20204 for ; Thu, 7 Apr 2016 16:37:58 +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 74F7320166 for ; Thu, 7 Apr 2016 16:37:57 +0000 (UTC) Received: from localhost ([::1]:51334 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoCwO-00007B-TR for patchwork-qemu-devel@patchwork.kernel.org; Thu, 07 Apr 2016 12:37:56 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41279) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoCsP-0001PH-Cw for qemu-devel@nongnu.org; Thu, 07 Apr 2016 12:33:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aoCsN-0005lM-Qf for qemu-devel@nongnu.org; Thu, 07 Apr 2016 12:33:49 -0400 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]:35116) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoCsN-0005lB-8v; Thu, 07 Apr 2016 12:33:47 -0400 Received: by mail-wm0-x241.google.com with SMTP id a140so22764076wma.2; Thu, 07 Apr 2016 09:33:47 -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=DyQLPED+BFSTzeG6iwbggc6x44ORVoXFWe0paBsckEI=; b=rncoWwX+S0R5uLP5pQLb9T/gzyKpsgrmdmBWneGbj16902XWSQ9Rins52dkNBihG0x bDotOV+OYGaNBXsn1dU11eKEpu5/Vf18at1CuX7PbLZkongeat6EzCqxXgD1ZzymQnfu r3ugxv6fHH5mXzMo8KRDza6lOwvWH1rEBV6p/kavUSit+GSc38YeZyhBZJc8eJI9qwL4 BNGc9KNtNDpgorgF6l3Ek4qrbXJ0XLDuann6djBrSi6YTFQbA5/l1D7M3zucUCBmjtIe 7zCTfEkkdTBI2C1IgVtr41tTj/H+ZH3sI1BDfnZmDPJv6Hgb/n+ZzLMTRsrP0889GxB2 QHOA== 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=DyQLPED+BFSTzeG6iwbggc6x44ORVoXFWe0paBsckEI=; b=PiNOM+LAj/tNKkZHGe3/pgooDb3UbsBjmhr+8dSxzEJ3TSmmK1zaL1rkmRJIRb1Qz/ jpESQYqNDTYiidXEKS9Rw93AS7LQmWBwgxfnL3UW4lpcgUDQl8AfrQCw04aF3pu0JmxV QKJnby5/u+Lr94PQAFhmo6x08HcFIEK/4UQVjv/DlvFh0FlZwLQPQRRKh7+EcwvM6T2b VDD7tl39Jprvz/EpMCCO6SFb8GLgdOg29AkuYRjGTX5Kti1Hxusa5t/PrwETFBuRj9WZ dG8ktJQZTjJdbsLbilJD0Vh9OQ0NRA9Y/+uh9xOVcWuNk5nppmvdCl1gi0X+vQEgtNTB QzcQ== X-Gm-Message-State: AD7BkJJP33djdaIT0CE5zrinn5qNUtaYXVVZFlkVEGL7TULQGFpLUaAAn77h1ArRdUPP0g== X-Received: by 10.28.107.13 with SMTP id g13mr5356775wmc.62.1460046826632; Thu, 07 Apr 2016 09:33:46 -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.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Apr 2016 09:33:45 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 7 Apr 2016 18:33:34 +0200 Message-Id: <1460046816-102846-7-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::241 Cc: kwolf@redhat.com, berto@igalia.com, famz@redhat.com, qemu-block@nongnu.org, stefanha@redhat.com Subject: [Qemu-devel] [PATCH v4 6/8] block: plug whole tree at once, introduce bdrv_io_unplugged_begin/end 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 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 --- v3->v4: unplug children after parent, plug children before parent; bdrv_io_plug/unplug did it one way, bdrv_io_unplugged_begin/end didn't [Paolo] 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 fbcf954..6b25216 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; };