From nobody Wed Nov 5 19:37:14 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1496391365360607.555166099373; Fri, 2 Jun 2017 01:16:05 -0700 (PDT) Received: from localhost ([::1]:48440 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dGhkZ-0005cR-W6 for importer@patchew.org; Fri, 02 Jun 2017 04:16:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dGhgb-0001qR-Ob for qemu-devel@nongnu.org; Fri, 02 Jun 2017 04:12:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dGhga-0002Jg-FH for qemu-devel@nongnu.org; Fri, 02 Jun 2017 04:11:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43414) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dGhga-0002Iw-6I for qemu-devel@nongnu.org; Fri, 02 Jun 2017 04:11:56 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3D2E380F93; Fri, 2 Jun 2017 08:11:55 +0000 (UTC) Received: from lemon.redhat.com (ovpn-12-49.pek2.redhat.com [10.72.12.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id 77F1F60A99; Fri, 2 Jun 2017 08:11:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 3D2E380F93 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=famz@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 3D2E380F93 From: Fam Zheng To: qemu-devel@nongnu.org Date: Fri, 2 Jun 2017 16:11:09 +0800 Message-Id: <20170602081120.3497-12-famz@redhat.com> In-Reply-To: <20170602081120.3497-1-famz@redhat.com> References: <20170602081120.3497-1-famz@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 02 Jun 2017 08:11:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL v2 11/22] throttle-groups: only start one coroutine from drained_begin 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: peter.maydell@linaro.org, Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Paolo Bonzini Starting all waiting coroutines from bdrv_drain_all is unnecessary; throttle_group_co_io_limits_intercept calls schedule_next_request as soon as the coroutine restarts, which in turn will restart the next request if possible. If we only start the first request and let the coroutines dance from there the code is simpler and there is more reuse between throttle_group_config, throttle_group_restart_blk and timer_cb. The next patch will benefit from this. We also stop accessing from throttle_group_restart_blk the blkp->throttled_reqs CoQueues even when there was no attached throttling group. This worked but is not pretty. The only thing that can interrupt the dance is the QEMU_CLOCK_VIRTUAL timer when switching from one block device to the next, because the timer is set to "now + 1" but QEMU_CLOCK_VIRTUAL might not be running. Set that timer to point in the present ("now") rather than the future and things work. Reviewed-by: Alberto Garcia Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Message-Id: <20170525163225.29954-8-pbonzini@redhat.com> Signed-off-by: Fam Zheng --- block/throttle-groups.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/block/throttle-groups.c b/block/throttle-groups.c index 69bfbd4..85169ec 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -292,7 +292,7 @@ static void schedule_next_request(BlockBackend *blk, bo= ol is_write) } else { ThrottleTimers *tt =3D &blk_get_public(token)->throttle_timers; int64_t now =3D qemu_clock_get_ns(tt->clock_type); - timer_mod(tt->timers[is_write], now + 1); + timer_mod(tt->timers[is_write], now); tg->any_timer_armed[is_write] =3D true; } tg->tokens[is_write] =3D token; @@ -340,15 +340,32 @@ void coroutine_fn throttle_group_co_io_limits_interce= pt(BlockBackend *blk, qemu_mutex_unlock(&tg->lock); } =20 +static void throttle_group_restart_queue(BlockBackend *blk, bool is_write) +{ + BlockBackendPublic *blkp =3D blk_get_public(blk); + ThrottleGroup *tg =3D container_of(blkp->throttle_state, ThrottleGroup= , ts); + bool empty_queue; + + aio_context_acquire(blk_get_aio_context(blk)); + empty_queue =3D !qemu_co_enter_next(&blkp->throttled_reqs[is_write]); + aio_context_release(blk_get_aio_context(blk)); + + /* If the request queue was empty then we have to take care of + * scheduling the next one */ + if (empty_queue) { + qemu_mutex_lock(&tg->lock); + schedule_next_request(blk, is_write); + qemu_mutex_unlock(&tg->lock); + } +} + void throttle_group_restart_blk(BlockBackend *blk) { BlockBackendPublic *blkp =3D blk_get_public(blk); - int i; =20 - for (i =3D 0; i < 2; i++) { - while (qemu_co_enter_next(&blkp->throttled_reqs[i])) { - ; - } + if (blkp->throttle_state) { + throttle_group_restart_queue(blk, 0); + throttle_group_restart_queue(blk, 1); } } =20 @@ -376,8 +393,7 @@ void throttle_group_config(BlockBackend *blk, ThrottleC= onfig *cfg) throttle_config(ts, tt, cfg); qemu_mutex_unlock(&tg->lock); =20 - qemu_co_enter_next(&blkp->throttled_reqs[0]); - qemu_co_enter_next(&blkp->throttled_reqs[1]); + throttle_group_restart_blk(blk); } =20 /* Get the throttle configuration from a particular group. Similar to @@ -408,7 +424,6 @@ static void timer_cb(BlockBackend *blk, bool is_write) BlockBackendPublic *blkp =3D blk_get_public(blk); ThrottleState *ts =3D blkp->throttle_state; ThrottleGroup *tg =3D container_of(ts, ThrottleGroup, ts); - bool empty_queue; =20 /* The timer has just been fired, so we can update the flag */ qemu_mutex_lock(&tg->lock); @@ -416,17 +431,7 @@ static void timer_cb(BlockBackend *blk, bool is_write) qemu_mutex_unlock(&tg->lock); =20 /* Run the request that was waiting for this timer */ - aio_context_acquire(blk_get_aio_context(blk)); - empty_queue =3D !qemu_co_enter_next(&blkp->throttled_reqs[is_write]); - aio_context_release(blk_get_aio_context(blk)); - - /* If the request queue was empty then we have to take care of - * scheduling the next one */ - if (empty_queue) { - qemu_mutex_lock(&tg->lock); - schedule_next_request(blk, is_write); - qemu_mutex_unlock(&tg->lock); - } + throttle_group_restart_queue(blk, is_write); } =20 static void read_timer_cb(void *opaque) --=20 2.9.4