From nobody Fri May 3 19:51:13 2024 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 1492690322924393.25057050730277; Thu, 20 Apr 2017 05:12:02 -0700 (PDT) Received: from localhost ([::1]:53585 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1AwK-0007Qg-Jm for importer@patchew.org; Thu, 20 Apr 2017 08:12:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38623) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Aml-0007aT-I6 for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1AmY-0002vp-Jg for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34038) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alj-0002GC-EA; Thu, 20 Apr 2017 08:01:03 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 20A3834144C; Thu, 20 Apr 2017 12:01:02 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3p002037; Thu, 20 Apr 2017 08:01:01 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 20A3834144C Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 20A3834144C From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:42 +0200 Message-Id: <20170420120058.28404-2-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 20 Apr 2017 12:01:02 +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] [PATCH 01/17] block: access copy_on_read with atomic ops 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block.c | 6 ++++-- block/io.c | 8 ++++---- blockdev.c | 2 +- include/block/block_int.h | 11 ++++++----- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/block.c b/block.c index 1fbbb8d..a48fdd8 100644 --- a/block.c +++ b/block.c @@ -1189,7 +1189,9 @@ static int bdrv_open_common(BlockDriverState *bs, Blo= ckBackend *file, goto fail_opts; } =20 - assert(bs->copy_on_read =3D=3D 0); /* bdrv_new() and bdrv_close() make= it so */ + /* bdrv_new() and bdrv_close() make it so */ + assert(atomic_read(&bs->copy_on_read) =3D=3D 0); + if (bs->open_flags & BDRV_O_COPY_ON_READ) { if (!bs->read_only) { bdrv_enable_copy_on_read(bs); @@ -2937,7 +2939,7 @@ static void bdrv_close(BlockDriverState *bs) =20 g_free(bs->opaque); bs->opaque =3D NULL; - bs->copy_on_read =3D 0; + atomic_set(&bs->copy_on_read, 0); bs->backing_file[0] =3D '\0'; bs->backing_format[0] =3D '\0'; bs->total_sectors =3D 0; diff --git a/block/io.c b/block/io.c index a54e5c8..08de488 100644 --- a/block/io.c +++ b/block/io.c @@ -130,13 +130,13 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error = **errp) */ void bdrv_enable_copy_on_read(BlockDriverState *bs) { - bs->copy_on_read++; + atomic_inc(&bs->copy_on_read); } =20 void bdrv_disable_copy_on_read(BlockDriverState *bs) { - assert(bs->copy_on_read > 0); - bs->copy_on_read--; + assert(atomic_read(&bs->copy_on_read) > 0); + atomic_dec(&bs->copy_on_read); } =20 /* Check if any requests are in-flight (including throttled requests) */ @@ -1144,7 +1144,7 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, bdrv_inc_in_flight(bs); =20 /* Don't do copy-on-read if we read data before write operation */ - if (bs->copy_on_read && !(flags & BDRV_REQ_NO_SERIALISING)) { + if (atomic_read(&bs->copy_on_read) && !(flags & BDRV_REQ_NO_SERIALISIN= G)) { flags |=3D BDRV_REQ_COPY_ON_READ; } =20 diff --git a/blockdev.c b/blockdev.c index 9098233..e9b5717 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1794,7 +1794,7 @@ static void external_snapshot_commit(BlkActionState *= common) /* We don't need (or want) to use the transactional * bdrv_reopen_multiple() across all the entries at once, because we * don't want to abort all of them if one of them fails the reopen */ - if (!state->old_bs->copy_on_read) { + if (!atomic_read(&state->old_bs->copy_on_read)) { bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDW= R, NULL); } diff --git a/include/block/block_int.h b/include/block/block_int.h index 59400bd..d0b88ff 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -581,11 +581,6 @@ struct BlockDriverState { =20 /* Protected by AioContext lock */ =20 - /* If true, copy read backing sectors into image. Can be >1 if more - * than one client has requested copy-on-read. - */ - int copy_on_read; - /* If we are reading a disk image, give its size in sectors. * Generally read-only; it is written to by load_vmstate and save_vmst= ate, * but the block layer is quiescent during those. @@ -619,6 +614,12 @@ struct BlockDriverState { =20 QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps; =20 + /* If true, copy read backing sectors into image. Can be >1 if more + * than one client has requested copy-on-read. Accessed with atomic + * ops. + */ + int copy_on_read; + /* do we need to tell the quest if we have a volatile write cache? */ int enable_write_cache; =20 --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690174434696.689570537683; Thu, 20 Apr 2017 05:09:34 -0700 (PDT) Received: from localhost ([::1]:53563 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Att-0005DD-Qs for importer@patchew.org; Thu, 20 Apr 2017 08:09:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38653) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amm-0007bt-HV for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Amc-00031g-9i for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34460) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alo-0002NV-BE; Thu, 20 Apr 2017 08:01:08 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 95BD7C04D2BC; Thu, 20 Apr 2017 12:01:03 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3q002037; Thu, 20 Apr 2017 08:01:02 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 95BD7C04D2BC Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 95BD7C04D2BC From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:43 +0200 Message-Id: <20170420120058.28404-3-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 20 Apr 2017 12:01:03 +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] [PATCH 02/17] block: access quiesce_counter with atomic ops 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- block/io.c | 4 ++-- include/block/block_int.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/block/io.c b/block/io.c index 08de488..3a27fd5 100644 --- a/block/io.c +++ b/block/io.c @@ -241,7 +241,7 @@ void bdrv_drained_begin(BlockDriverState *bs) return; } =20 - if (!bs->quiesce_counter++) { + if (atomic_fetch_inc(&bs->quiesce_counter) =3D=3D 0) { aio_disable_external(bdrv_get_aio_context(bs)); bdrv_parent_drained_begin(bs); } @@ -252,7 +252,7 @@ void bdrv_drained_begin(BlockDriverState *bs) void bdrv_drained_end(BlockDriverState *bs) { assert(bs->quiesce_counter > 0); - if (--bs->quiesce_counter > 0) { + if (atomic_fetch_dec(&bs->quiesce_counter) > 1) { return; } =20 diff --git a/include/block/block_int.h b/include/block/block_int.h index d0b88ff..a43fe78 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -623,6 +623,7 @@ struct BlockDriverState { /* do we need to tell the quest if we have a volatile write cache? */ int enable_write_cache; =20 + /* Accessed with atomic ops. */ int quiesce_counter; }; =20 --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690183394985.0926933090961; Thu, 20 Apr 2017 05:09:43 -0700 (PDT) Received: from localhost ([::1]:53564 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Au5-0005M9-R0 for importer@patchew.org; Thu, 20 Apr 2017 08:09:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38626) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Aml-0007ab-Nu for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Amf-00033B-Lv for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34218) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alp-0002OK-Pf; Thu, 20 Apr 2017 08:01:09 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 0C4F9341467; Thu, 20 Apr 2017 12:01:05 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3r002037; Thu, 20 Apr 2017 08:01:04 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 0C4F9341467 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 0C4F9341467 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:44 +0200 Message-Id: <20170420120058.28404-4-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 20 Apr 2017 12:01:05 +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] [PATCH 03/17] block: access io_limits_disabled with atomic ops 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- block/block-backend.c | 4 ++-- block/throttle-groups.c | 2 +- include/sysemu/block-backend.h | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 7405024..915ccc5 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1927,7 +1927,7 @@ static void blk_root_drained_begin(BdrvChild *child) /* Note that blk->root may not be accessible here yet if we are just * attaching to a BlockDriverState that is drained. Use child instead.= */ =20 - if (blk->public.io_limits_disabled++ =3D=3D 0) { + if (atomic_fetch_inc(&blk->public.io_limits_disabled) =3D=3D 0) { throttle_group_restart_blk(blk); } } @@ -1938,7 +1938,7 @@ static void blk_root_drained_end(BdrvChild *child) assert(blk->quiesce_counter); =20 assert(blk->public.io_limits_disabled); - --blk->public.io_limits_disabled; + atomic_dec(&blk->public.io_limits_disabled); =20 if (--blk->quiesce_counter =3D=3D 0) { if (blk->dev_ops && blk->dev_ops->drained_end) { diff --git a/block/throttle-groups.c b/block/throttle-groups.c index b73e7a8..69bfbd4 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -240,7 +240,7 @@ static bool throttle_group_schedule_timer(BlockBackend = *blk, bool is_write) ThrottleGroup *tg =3D container_of(ts, ThrottleGroup, ts); bool must_wait; =20 - if (blkp->io_limits_disabled) { + if (atomic_read(&blkp->io_limits_disabled)) { return false; } =20 diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 7462228..87a43b0 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -80,7 +80,8 @@ typedef struct BlockBackendPublic { CoQueue throttled_reqs[2]; =20 /* Nonzero if the I/O limits are currently being ignored; generally - * it is zero. */ + * it is zero. Accessed with atomic operations. + */ unsigned int io_limits_disabled; =20 /* The following fields are protected by the ThrottleGroup lock. --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690118524216.8729811204646; Thu, 20 Apr 2017 05:08:38 -0700 (PDT) Received: from localhost ([::1]:53561 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1At2-0004SY-Ln for importer@patchew.org; Thu, 20 Apr 2017 08:08:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38744) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amq-0007gZ-4t for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Ami-00034h-Pf for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54226) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alo-0002Nd-B6; Thu, 20 Apr 2017 08:01:08 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 DA565ADAEF; Thu, 20 Apr 2017 12:01:06 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3s002037; Thu, 20 Apr 2017 08:01:05 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com DA565ADAEF Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com DA565ADAEF From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:45 +0200 Message-Id: <20170420120058.28404-5-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Thu, 20 Apr 2017 12:01:07 +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] [PATCH 04/17] block: access serialising_in_flight with atomic ops 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- block/io.c | 6 +++--- include/block/block_int.h | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/block/io.c b/block/io.c index 3a27fd5..869322a 100644 --- a/block/io.c +++ b/block/io.c @@ -375,7 +375,7 @@ void bdrv_drain_all(void) static void tracked_request_end(BdrvTrackedRequest *req) { if (req->serialising) { - req->bs->serialising_in_flight--; + atomic_dec(&req->bs->serialising_in_flight); } =20 QLIST_REMOVE(req, list); @@ -414,7 +414,7 @@ static void mark_request_serialising(BdrvTrackedRequest= *req, uint64_t align) - overlap_offset; =20 if (!req->serialising) { - req->bs->serialising_in_flight++; + atomic_inc(&req->bs->serialising_in_flight); req->serialising =3D true; } =20 @@ -519,7 +519,7 @@ static bool coroutine_fn wait_serialising_requests(Bdrv= TrackedRequest *self) bool retry; bool waited =3D false; =20 - if (!bs->serialising_in_flight) { + if (!atomic_read(&bs->serialising_in_flight)) { return false; } =20 diff --git a/include/block/block_int.h b/include/block/block_int.h index a43fe78..7317db6 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -590,10 +590,6 @@ struct BlockDriverState { /* Callback before write request is processed */ NotifierWithReturnList before_write_notifiers; =20 - /* number of in-flight requests; overall and serialising */ - unsigned int in_flight; - unsigned int serialising_in_flight; - bool wakeup; =20 /* Offset after the highest byte written to */ @@ -620,6 +616,12 @@ struct BlockDriverState { */ int copy_on_read; =20 + /* number of in-flight requests; overall and serialising. + * Accessed with atomic ops. + */ + unsigned int in_flight; + unsigned int serialising_in_flight; + /* do we need to tell the quest if we have a volatile write cache? */ int enable_write_cache; =20 --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690021689355.7916297879051; Thu, 20 Apr 2017 05:07:01 -0700 (PDT) Received: from localhost ([::1]:53548 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1ArT-00031B-Ts for importer@patchew.org; Thu, 20 Apr 2017 08:06:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38600) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amk-0007Z9-GC for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1AmZ-0002wo-5Y for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:06 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34254) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alr-0002Oo-0A; Thu, 20 Apr 2017 08:01:11 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 6453D34147B; Thu, 20 Apr 2017 12:01:09 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3t002037; Thu, 20 Apr 2017 08:01:07 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6453D34147B Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 6453D34147B From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:46 +0200 Message-Id: <20170420120058.28404-6-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 20 Apr 2017 12:01:09 +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] [PATCH 05/17] block: access wakeup with atomic ops 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block/io.c | 3 ++- block/nfs.c | 4 +++- block/sheepdog.c | 3 ++- include/block/block.h | 5 +++-- include/block/block_int.h | 4 ++-- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/block/io.c b/block/io.c index 869322a..3b2ede9 100644 --- a/block/io.c +++ b/block/io.c @@ -501,7 +501,8 @@ static void dummy_bh_cb(void *opaque) =20 void bdrv_wakeup(BlockDriverState *bs) { - if (bs->wakeup) { + /* The barrier (or an atomic op) is in the caller. */ + if (atomic_read(&bs->wakeup)) { aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL); } } diff --git a/block/nfs.c b/block/nfs.c index 0816678..fd2508a 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -736,7 +736,9 @@ nfs_get_allocated_file_size_cb(int ret, struct nfs_cont= ext *nfs, void *data, if (task->ret < 0) { error_report("NFS Error: %s", nfs_get_error(nfs)); } - task->complete =3D 1; + + /* Set task->complete before reading bs->wakeup. */ + atomic_mb_set(&task->complete, 1); bdrv_wakeup(task->bs); } =20 diff --git a/block/sheepdog.c b/block/sheepdog.c index fb9203e..7e90a24 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -704,7 +704,8 @@ out: =20 srco->co =3D NULL; srco->ret =3D ret; - srco->finished =3D true; + /* Set srco->finished before reading bs->wakeup. */ + atomic_mb_set(&srco->finished, true); if (srco->bs) { bdrv_wakeup(srco->bs); } diff --git a/include/block/block.h b/include/block/block.h index 5ddc0cf..486b6ed 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -398,7 +398,8 @@ void bdrv_drain_all(void); * block_job_defer_to_main_loop for how to do it). \ */ \ assert(!bs_->wakeup); \ - bs_->wakeup =3D true; \ + /* Set bs->wakeup before evaluating cond. */ \ + atomic_mb_set(&bs_->wakeup, true); \ while (busy_) { \ if ((cond)) { \ waited_ =3D busy_ =3D true; \ @@ -410,7 +411,7 @@ void bdrv_drain_all(void); waited_ |=3D busy_; \ } \ } \ - bs_->wakeup =3D false; \ + atomic_set(&bs_->wakeup, false); \ } \ waited_; }) =20 diff --git a/include/block/block_int.h b/include/block/block_int.h index 7317db6..ca34c99 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -590,8 +590,6 @@ struct BlockDriverState { /* Callback before write request is processed */ NotifierWithReturnList before_write_notifiers; =20 - bool wakeup; - /* Offset after the highest byte written to */ uint64_t wr_highest_offset; =20 @@ -622,6 +620,8 @@ struct BlockDriverState { unsigned int in_flight; unsigned int serialising_in_flight; =20 + bool wakeup; + /* do we need to tell the quest if we have a volatile write cache? */ int enable_write_cache; =20 --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492689879758413.0770683816396; Thu, 20 Apr 2017 05:04:39 -0700 (PDT) Received: from localhost ([::1]:53535 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1ApB-0000w6-V0 for importer@patchew.org; Thu, 20 Apr 2017 08:04:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38530) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amg-0007W2-P8 for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1AmY-0002w3-LA for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:02 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41168) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alr-0002Pw-J9; Thu, 20 Apr 2017 08:01:11 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 4539D67EC3; Thu, 20 Apr 2017 12:01:10 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3u002037; Thu, 20 Apr 2017 08:01:09 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4539D67EC3 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 4539D67EC3 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:47 +0200 Message-Id: <20170420120058.28404-7-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 20 Apr 2017 12:01:10 +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] [PATCH 06/17] block: access io_plugged with atomic ops 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- block/io.c | 4 ++-- include/block/block_int.h | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/block/io.c b/block/io.c index 3b2ede9..3ab9476 100644 --- a/block/io.c +++ b/block/io.c @@ -2653,7 +2653,7 @@ void bdrv_io_plug(BlockDriverState *bs) bdrv_io_plug(child->bs); } =20 - if (bs->io_plugged++ =3D=3D 0) { + if (atomic_fetch_inc(&bs->io_plugged) =3D=3D 0) { BlockDriver *drv =3D bs->drv; if (drv && drv->bdrv_io_plug) { drv->bdrv_io_plug(bs); @@ -2666,7 +2666,7 @@ void bdrv_io_unplug(BlockDriverState *bs) BdrvChild *child; =20 assert(bs->io_plugged); - if (--bs->io_plugged =3D=3D 0) { + if (atomic_fetch_dec(&bs->io_plugged) =3D=3D 1) { BlockDriver *drv =3D bs->drv; if (drv && drv->bdrv_io_unplug) { drv->bdrv_io_unplug(bs); diff --git a/include/block/block_int.h b/include/block/block_int.h index ca34c99..283d079 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -597,9 +597,6 @@ struct BlockDriverState { uint64_t write_threshold_offset; NotifierWithReturn write_threshold_notifier; =20 - /* counter for nested bdrv_io_plug */ - unsigned io_plugged; - QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; CoQueue flush_queue; /* Serializing flush queue */ bool active_flush_req; /* Flush request in flight? */ @@ -622,6 +619,11 @@ struct BlockDriverState { =20 bool wakeup; =20 + /* counter for nested bdrv_io_plug. + * Accessed with atomic ops. + */ + unsigned io_plugged; + /* do we need to tell the quest if we have a volatile write cache? */ int enable_write_cache; =20 --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690033120646.0796361839978; Thu, 20 Apr 2017 05:07:13 -0700 (PDT) Received: from localhost ([::1]:53549 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Arf-00037S-A0 for importer@patchew.org; Thu, 20 Apr 2017 08:07:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38554) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amh-0007W5-P9 for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Ama-0002yK-1L for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43726) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alt-0002RK-0f; Thu, 20 Apr 2017 08:01:13 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 D8854C7050; Thu, 20 Apr 2017 12:01:11 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3v002037; Thu, 20 Apr 2017 08:01:10 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D8854C7050 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com D8854C7050 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:48 +0200 Message-Id: <20170420120058.28404-8-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 20 Apr 2017 12:01:12 +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] [PATCH 07/17] throttle-groups: do not use qemu_co_enter_next 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: qemu-block@nongnu.org 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" Prepare for removing this function; always restart throttled requests from coroutine context. This will matter when restarting throttled requests will have to acquire a CoMutex. Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block/throttle-groups.c | 65 +++++++++++++++++++++++++++++++++++++++++++--= ---- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/block/throttle-groups.c b/block/throttle-groups.c index 69bfbd4..d66bf62 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -260,6 +260,18 @@ static bool throttle_group_schedule_timer(BlockBackend= *blk, bool is_write) return must_wait; } =20 +/* Start the next pending I/O request for a BlockBackend. + * + * @blk: the current BlockBackend + * @is_write: the type of operation (read/write) + */ +static bool throttle_group_co_restart_queue(BlockBackend *blk, bool is_wri= te) +{ + BlockBackendPublic *blkp =3D blk_get_public(blk); + + return qemu_co_queue_next(&blkp->throttled_reqs[is_write]); +} + /* Look for the next pending I/O request and schedule it. * * This assumes that tg->lock is held. @@ -287,7 +299,7 @@ static void schedule_next_request(BlockBackend *blk, bo= ol is_write) if (!must_wait) { /* Give preference to requests from the current blk */ if (qemu_in_coroutine() && - qemu_co_queue_next(&blkp->throttled_reqs[is_write])) { + throttle_group_co_restart_queue(blk, is_write)) { token =3D blk; } else { ThrottleTimers *tt =3D &blk_get_public(token)->throttle_timers; @@ -340,18 +352,57 @@ void coroutine_fn throttle_group_co_io_limits_interce= pt(BlockBackend *blk, qemu_mutex_unlock(&tg->lock); } =20 -void throttle_group_restart_blk(BlockBackend *blk) +typedef struct { + BlockBackend *blk; + bool is_write; + int ret; +} RestartData; + +static void throttle_group_restart_queue_entry(void *opaque) { - BlockBackendPublic *blkp =3D blk_get_public(blk); + RestartData *data =3D opaque; + + data->ret =3D throttle_group_co_restart_queue(data->blk, data->is_writ= e); +} + +static int throttle_group_restart_queue(BlockBackend *blk, bool is_write) +{ + Coroutine *co; + RestartData rd =3D { + .blk =3D blk, + .is_write =3D is_write + }; + + aio_context_acquire(blk_get_aio_context(blk)); + co =3D qemu_coroutine_create(throttle_group_restart_queue_entry, &rd); + /* The request doesn't start until after throttle_group_restart_queue_= entry + * returns, so the coroutine cannot yield. + */ + qemu_coroutine_enter(co); + aio_context_release(blk_get_aio_context(blk)); + return rd.ret; +} + +static void throttle_group_restart_blk_entry(void *opaque) +{ + BlockBackend *blk =3D opaque; int i; =20 for (i =3D 0; i < 2; i++) { - while (qemu_co_enter_next(&blkp->throttled_reqs[i])) { + while (throttle_group_co_restart_queue(blk, i)) { ; } } } =20 +void throttle_group_restart_blk(BlockBackend *blk) +{ + Coroutine *co; + + co =3D qemu_coroutine_create(throttle_group_restart_blk_entry, blk); + qemu_coroutine_enter(co); +} + /* Update the throttle configuration for a particular group. Similar * to throttle_config(), but guarantees atomicity within the * throttling group. @@ -376,8 +427,8 @@ 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_queue(blk, 0); + throttle_group_restart_queue(blk, 1); } =20 /* Get the throttle configuration from a particular group. Similar to @@ -417,7 +468,7 @@ static void timer_cb(BlockBackend *blk, bool is_write) =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]); + empty_queue =3D !throttle_group_restart_queue(blk, is_write); aio_context_release(blk_get_aio_context(blk)); =20 /* If the request queue was empty then we have to take care of --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 149269055208970.69745736320999; Thu, 20 Apr 2017 05:15:52 -0700 (PDT) Received: from localhost ([::1]:53621 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1B02-0001Xg-Nz for importer@patchew.org; Thu, 20 Apr 2017 08:15:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38670) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amn-0007cR-3D for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Ama-0002yS-7t for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34568) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alv-0002SQ-2x; Thu, 20 Apr 2017 08:01:15 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 503AFC0467F3; Thu, 20 Apr 2017 12:01:13 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3w002037; Thu, 20 Apr 2017 08:01:12 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 503AFC0467F3 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 503AFC0467F3 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:49 +0200 Message-Id: <20170420120058.28404-9-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 20 Apr 2017 12:01:13 +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] [PATCH 08/17] throttle-groups: protect throttled requests with a CoMutex 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block/block-backend.c | 1 + block/throttle-groups.c | 11 +++++++++-- include/sysemu/block-backend.h | 7 ++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 915ccc5..a37d74d 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -163,6 +163,7 @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_pe= rm) blk->shared_perm =3D shared_perm; blk_set_enable_write_cache(blk, true); =20 + qemu_co_mutex_init(&blk->public.reqs_lock); qemu_co_queue_init(&blk->public.throttled_reqs[0]); qemu_co_queue_init(&blk->public.throttled_reqs[1]); =20 diff --git a/block/throttle-groups.c b/block/throttle-groups.c index d66bf62..695d28d 100644 --- a/block/throttle-groups.c +++ b/block/throttle-groups.c @@ -268,8 +268,13 @@ static bool throttle_group_schedule_timer(BlockBackend= *blk, bool is_write) static bool throttle_group_co_restart_queue(BlockBackend *blk, bool is_wri= te) { BlockBackendPublic *blkp =3D blk_get_public(blk); + bool ret; =20 - return qemu_co_queue_next(&blkp->throttled_reqs[is_write]); + qemu_co_mutex_lock(&blkp->reqs_lock); + ret =3D qemu_co_queue_next(&blkp->throttled_reqs[is_write]); + qemu_co_mutex_unlock(&blkp->reqs_lock); + + return ret; } =20 /* Look for the next pending I/O request and schedule it. @@ -338,7 +343,9 @@ void coroutine_fn throttle_group_co_io_limits_intercept= (BlockBackend *blk, if (must_wait || blkp->pending_reqs[is_write]) { blkp->pending_reqs[is_write]++; qemu_mutex_unlock(&tg->lock); - qemu_co_queue_wait(&blkp->throttled_reqs[is_write], NULL); + qemu_co_mutex_lock(&blkp->reqs_lock); + qemu_co_queue_wait(&blkp->throttled_reqs[is_write], &blkp->reqs_lo= ck); + qemu_co_mutex_unlock(&blkp->reqs_lock); qemu_mutex_lock(&tg->lock); blkp->pending_reqs[is_write]--; } diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 87a43b0..e9529fb 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -72,11 +72,8 @@ typedef struct BlockDevOps { * fields that must be public. This is in particular for QLIST_ENTRY() and * friends so that BlockBackends can be kept in lists outside block-backen= d.c */ typedef struct BlockBackendPublic { - /* I/O throttling has its own locking, but also some fields are - * protected by the AioContext lock. - */ - - /* Protected by AioContext lock. */ + /* reqs_lock protects the CoQueues for throttled requests. */ + CoMutex reqs_lock; CoQueue throttled_reqs[2]; =20 /* Nonzero if the I/O limits are currently being ignored; generally --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492689968331909.2816170740059; Thu, 20 Apr 2017 05:06:08 -0700 (PDT) Received: from localhost ([::1]:53546 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Aqc-0002FY-LF for importer@patchew.org; Thu, 20 Apr 2017 08:06:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38717) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amo-0007eU-BO for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Amb-000314-Qv for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34430) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alv-0002Si-QL; Thu, 20 Apr 2017 08:01:16 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 AC0F734156A; Thu, 20 Apr 2017 12:01:14 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w3x002037; Thu, 20 Apr 2017 08:01:13 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com AC0F734156A Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com AC0F734156A From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:50 +0200 Message-Id: <20170420120058.28404-10-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 20 Apr 2017 12:01:14 +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] [PATCH 09/17] util: add stats64 module 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: qemu-block@nongnu.org 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" This module provides fast paths for 64-bit atomic operations on machines that only have 32-bit atomic access. Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- include/qemu/stats64.h | 210 +++++++++++++++++++++++++++++++++++++++++++++= ++++ util/Makefile.objs | 1 + util/stats64.c | 135 ++++++++++++++++++++++++++++++++ 3 files changed, 346 insertions(+) create mode 100644 include/qemu/stats64.h create mode 100644 util/stats64.c diff --git a/include/qemu/stats64.h b/include/qemu/stats64.h new file mode 100644 index 0000000..70963f4 --- /dev/null +++ b/include/qemu/stats64.h @@ -0,0 +1,210 @@ +/* + * Atomic operations on 64-bit quantities. + * + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_STATS64_H +#define QEMU_STATS64_H 1 + +#include "qemu/atomic.h" + +/* FIXME: i386 doesn't need the spinlock. Are there any others? */ +#if __SIZEOF_LONG__ < 8 +#define STAT64_NEED_SPINLOCK 1 +#endif + +/* This provides atomic operations on 64-bit type, using a reader-writer + * spinlock on architectures that do not have 64-bit accesses. However + * it tries hard not to take the lock. + */ + +typedef struct Stat64 { +#ifdef STAT64_NEED_SPINLOCK + uint32_t low, high; + uint32_t lock; +#else + uint64_t value; +#endif +} Stat64; + +#ifndef STAT64_NEED_SPINLOCK +static inline void stat64_init(Stat64 *s, uint64_t value) +{ + /* This is not guaranteed to be atomic! */ + *s =3D (Stat64) { value }; +} + +static inline uint64_t stat64_get(const Stat64 *s) +{ + return atomic_read(&s->value); +} + +static inline void stat64_add(Stat64 *s, uint64_t value) +{ + atomic_add(&s->value, value); +} + +static inline void stat64_min(Stat64 *s, uint32_t value) +{ + for (;;) { + uint64_t orig =3D atomic_read(&s->value); + if (orig <=3D value) { + break; + } + orig =3D atomic_cmpxchg(&s->value, orig, value); + if (orig <=3D value) { + break; + } + } +} + +static inline void stat64_max(Stat64 *s, uint32_t value) +{ + for (;;) { + uint64_t orig =3D atomic_read(&s->value); + if (orig >=3D value) { + break; + } + orig =3D atomic_cmpxchg(&s->value, orig, value); + if (orig >=3D value) { + break; + } + } +} +#else +uint64_t stat64_get(const Stat64 *s); +bool stat64_min_slow(Stat64 *s, uint64_t value); +bool stat64_max_slow(Stat64 *s, uint64_t value); +bool stat64_add32_carry(Stat64 *s, uint32_t low, uint32_t high); + +static inline void stat64_init(Stat64 *s, uint64_t value) +{ + /* This is not guaranteed to be atomic! */ + *s =3D (Stat64) { .low =3D value, .high =3D value >> 32, .lock =3D 0 }; +} + +static inline void stat64_add(Stat64 *s, uint64_t value) +{ + uint32_t low, high; + high =3D value >> 32; + low =3D (uint32_t) value; + if (!low) { + if (high) { + atomic_add(&s->high, high); + } + return; + } + + for (;;) { + uint32_t orig =3D s->low; + uint32_t result =3D orig + low; + uint32_t old; + + if (result < low || high) { + /* If the high part is affected, take the lock. */ + if (stat64_add32_carry(s, low, high)) { + return; + } + continue; + } + + /* No carry, try with a 32-bit cmpxchg. The result is independent= of + * the high 32 bits, so it can race just fine with stat64_add32_ca= rry + * and even stat64_get! + */ + old =3D atomic_cmpxchg(&s->low, orig, result); + if (orig =3D=3D old) { + return; + } + } +} + +static inline void stat64_min(Stat64 *s, uint64_t value) +{ + uint32_t low, high; + uint32_t orig_low, orig_high; + + high =3D value >> 32; + low =3D (uint32_t) value; + do { + orig_high =3D atomic_read(&s->high); + if (orig_high < high) { + return; + } + + if (orig_high =3D=3D high) { + /* High 32 bits are equal. Read low after high, otherwise we + * can get a false positive (e.g. 0x1235,0x0000 changes to + * 0x1234,0x8000 and we read it as 0x1234,0x0000). Pairs with + * the write barrier in stat64_min_slow. + */ + smp_rmb(); + orig_low =3D atomic_read(&s->low); + if (orig_low <=3D low) { + return; + } + + /* See if we were lucky and a writer raced against us. The + * barrier is theoretically unnecessary, but if we remove it + * we may miss being lucky. + */ + smp_rmb(); + orig_high =3D atomic_read(&s->high); + if (orig_high < high) { + return; + } + } + + /* If the value changes in any way, we have to take the lock. */ + } while (!stat64_min_slow(s, value)); +} + +static inline void stat64_max(Stat64 *s, uint64_t value) +{ + uint32_t low, high; + uint32_t orig_low, orig_high; + + high =3D value >> 32; + low =3D (uint32_t) value; + do { + orig_high =3D atomic_read(&s->high); + if (orig_high > high) { + return; + } + + if (orig_high =3D=3D high) { + /* High 32 bits are equal. Read low after high, otherwise we + * can get a false positive (e.g. 0x1234,0x8000 changes to + * 0x1235,0x0000 and we read it as 0x1235,0x8000). Pairs with + * the write barrier in stat64_max_slow. + */ + smp_rmb(); + orig_low =3D atomic_read(&s->low); + if (orig_low >=3D low) { + return; + } + + /* See if we were lucky and a writer raced against us. The + * barrier is theoretically unnecessary, but if we remove it + * we may miss being lucky. + */ + smp_rmb(); + orig_high =3D atomic_read(&s->high); + if (orig_high > high) { + return; + } + } + + /* If the value changes in any way, we have to take the lock. */ + } while (!stat64_max_slow(s, value)); +} + +#endif + +#endif diff --git a/util/Makefile.objs b/util/Makefile.objs index c6205eb..8a333d3 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -42,4 +42,5 @@ util-obj-y +=3D log.o util-obj-y +=3D qdist.o util-obj-y +=3D qht.o util-obj-y +=3D range.o +util-obj-y +=3D stats64.o util-obj-y +=3D systemd.o diff --git a/util/stats64.c b/util/stats64.c new file mode 100644 index 0000000..b9238d7 --- /dev/null +++ b/util/stats64.c @@ -0,0 +1,135 @@ +/* + * Atomic operations on 64-bit quantities. + * + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/atomic.h" +#include "qemu/stats64.h" + +#ifdef STAT64_NEED_SPINLOCK +static inline void stat64_rdlock(Stat64 *s) +{ + /* Keep out incoming writers to avoid them starving us. */ + atomic_add(&s->lock, 2); + + /* If there is a concurrent writer, wait for it. */ + while (atomic_read(&s->lock) & 1) { + g_usleep(5); + } +} + +static inline void stat64_rdunlock(Stat64 *s) +{ + atomic_sub(&s->lock, 2); +} + +static inline bool stat64_wrtrylock(Stat64 *s) +{ + return atomic_cmpxchg(&s->lock, 0, 1) =3D=3D 0; +} + +static inline void stat64_wrunlock(Stat64 *s) +{ + atomic_dec(&s->lock); +} + +uint64_t stat64_get(const Stat64 *s) +{ + uint32_t high, low; + + stat64_rdlock((Stat64 *)s); + + /* 64-bit writes always take the lock, so we can read in + * any order. + */ + high =3D atomic_read(&s->high); + low =3D atomic_read(&s->low); + stat64_rdunlock((Stat64 *)s); + + return ((uint64_t)high << 32) | low; +} + +bool stat64_add32_carry(Stat64 *s, uint32_t low, uint32_t high) +{ + uint32_t old; + + if (!stat64_wrtrylock(s)) { + return false; + } + + /* 64-bit reads always take the lock, so they don't care about the + * order of our update. By updating s->low first, we can check + * whether we have to carry into s->high. + */ + old =3D atomic_fetch_add(&s->low, value); + high +=3D (old + value < old); + atomic_add(&s->high, high); + stat64_wrunlock(s); + return true; +} + +bool stat64_min_slow(Stat64 *s, uint64_t value) +{ + uint32_t high, low; + uint64_t orig; + + if (!stat64_wrtrylock(s)) { + return false; + } + + high =3D atomic_read(&s->high); + low =3D atomic_read(&s->low); + + orig =3D ((uint64_t)high << 32) | low; + if (orig < value) { + /* The value may become higher temporarily, but stat64_get does not + * notice (it takes the lock) and the only effect on stat64_min is + * that the slow path may be triggered unnecessarily. + * + * But, we have to set low before high, just like stat64_min reads + * high before low. + */ + atomic_set(&s->low, (uint32_t)value); + smp_wmb(); + atomic_set(&s->high, value >> 32); + } + stat64_wrunlock(s); + return true; +} + +bool stat64_max_slow(Stat64 *s, uint64_t value) +{ + uint32_t high, low; + uint64_t orig; + + if (!stat64_wrtrylock(s)) { + return false; + } + + high =3D atomic_read(&s->high); + low =3D atomic_read(&s->low); + + orig =3D ((uint64_t)high << 32) | low; + if (orig > value) { + /* The value may become lower temporarily, but stat64_get does not + * notice (it takes the lock) and the only effect on stat64_max is + * that the slow path may be triggered unnecessarily. + * + * But, we have to set low before high, just like stat64_max reads + * high before low. + */ + atomic_set(&s->low, (uint32_t)value); + smp_wmb(); + atomic_set(&s->high, value >> 32); + } + stat64_wrunlock(s); + return true; +} +#endif --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 149269000718165.5771351322901; Thu, 20 Apr 2017 05:06:47 -0700 (PDT) Received: from localhost ([::1]:53547 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1ArF-0002n3-EH for importer@patchew.org; Thu, 20 Apr 2017 08:06:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38663) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amm-0007cB-Qc for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Ama-0002zC-J3 for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41308) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Aly-0002Tu-6S; Thu, 20 Apr 2017 08:01:18 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 C0DAA680E5; Thu, 20 Apr 2017 12:01:15 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w40002037; Thu, 20 Apr 2017 08:01:14 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C0DAA680E5 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com C0DAA680E5 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:51 +0200 Message-Id: <20170420120058.28404-11-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 20 Apr 2017 12:01:15 +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] [PATCH 10/17] block: use Stat64 for wr_highest_offset 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- block/io.c | 4 +--- block/qapi.c | 2 +- include/block/block_int.h | 7 ++++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/block/io.c b/block/io.c index 3ab9476..fa8abff 100644 --- a/block/io.c +++ b/block/io.c @@ -1413,9 +1413,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChil= d *child, ++bs->write_gen; bdrv_set_dirty(bs, start_sector, end_sector - start_sector); =20 - if (bs->wr_highest_offset < offset + bytes) { - bs->wr_highest_offset =3D offset + bytes; - } + stat64_max(&bs->wr_highest_offset, offset + bytes); =20 if (ret >=3D 0) { bs->total_sectors =3D MAX(bs->total_sectors, end_sector); diff --git a/block/qapi.c b/block/qapi.c index a40922e..14b60ae 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -441,7 +441,7 @@ static BlockStats *bdrv_query_bds_stats(const BlockDriv= erState *bs, s->node_name =3D g_strdup(bdrv_get_node_name(bs)); } =20 - s->stats->wr_highest_offset =3D bs->wr_highest_offset; + s->stats->wr_highest_offset =3D stat64_get(&bs->wr_highest_offset); =20 if (bs->file) { s->has_parent =3D true; diff --git a/include/block/block_int.h b/include/block/block_int.h index 283d079..505c271 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -29,6 +29,7 @@ #include "qemu/option.h" #include "qemu/queue.h" #include "qemu/coroutine.h" +#include "qemu/stats64.h" #include "qemu/timer.h" #include "qapi-types.h" #include "qemu/hbitmap.h" @@ -590,9 +591,6 @@ struct BlockDriverState { /* Callback before write request is processed */ NotifierWithReturnList before_write_notifiers; =20 - /* Offset after the highest byte written to */ - uint64_t wr_highest_offset; - /* threshold limit for writes, in bytes. "High water mark". */ uint64_t write_threshold_offset; NotifierWithReturn write_threshold_notifier; @@ -605,6 +603,9 @@ struct BlockDriverState { =20 QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps; =20 + /* Offset after the highest byte written to */ + Stat64 wr_highest_offset; + /* If true, copy read backing sectors into image. Can be >1 if more * than one client has requested copy-on-read. Accessed with atomic * ops. --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492689870105705.6494114119399; Thu, 20 Apr 2017 05:04:30 -0700 (PDT) Received: from localhost ([::1]:53534 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Ap2-0000pw-2o for importer@patchew.org; Thu, 20 Apr 2017 08:04:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38584) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amj-0007Y7-J7 for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Amc-00031l-B4 for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:11888) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Am0-0002VX-Sz; Thu, 20 Apr 2017 08:01:21 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 0474AB0821; Thu, 20 Apr 2017 12:01:17 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w41002037; Thu, 20 Apr 2017 08:01:16 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 0474AB0821 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 0474AB0821 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:52 +0200 Message-Id: <20170420120058.28404-12-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 20 Apr 2017 12:01:17 +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] [PATCH 11/17] block: access write_gen with atomics 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- block.c | 2 +- block/io.c | 6 +++--- include/block/block_int.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/block.c b/block.c index a48fdd8..f1aec36 100644 --- a/block.c +++ b/block.c @@ -3294,7 +3294,7 @@ int bdrv_truncate(BdrvChild *child, int64_t offset) ret =3D refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS); bdrv_dirty_bitmap_truncate(bs); bdrv_parent_cb_resize(bs); - ++bs->write_gen; + atomic_inc(&bs->write_gen); } return ret; } diff --git a/block/io.c b/block/io.c index fa8abff..d17564b 100644 --- a/block/io.c +++ b/block/io.c @@ -1410,7 +1410,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChil= d *child, } bdrv_debug_event(bs, BLKDBG_PWRITEV_DONE); =20 - ++bs->write_gen; + atomic_inc(&bs->write_gen); bdrv_set_dirty(bs, start_sector, end_sector - start_sector); =20 stat64_max(&bs->wr_highest_offset, offset + bytes); @@ -2299,7 +2299,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) goto early_exit; } =20 - current_gen =3D bs->write_gen; + current_gen =3D atomic_read(&bs->write_gen); =20 /* Wait until any previous flushes are completed */ while (bs->active_flush_req) { @@ -2524,7 +2524,7 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *b= s, int64_t offset, } ret =3D 0; out: - ++bs->write_gen; + atomic_inc(&bs->write_gen); bdrv_set_dirty(bs, req.offset >> BDRV_SECTOR_BITS, req.bytes >> BDRV_SECTOR_BITS); tracked_request_end(&req); diff --git a/include/block/block_int.h b/include/block/block_int.h index 505c271..552680c 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -598,7 +598,6 @@ struct BlockDriverState { QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; CoQueue flush_queue; /* Serializing flush queue */ bool active_flush_req; /* Flush request in flight? */ - unsigned int write_gen; /* Current data generation */ unsigned int flushed_gen; /* Flushed write generation */ =20 QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps; @@ -630,6 +629,7 @@ struct BlockDriverState { =20 /* Accessed with atomic ops. */ int quiesce_counter; + unsigned int write_gen; /* Current data generation */ }; =20 struct BlockBackendRootState { --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690615457109.38936414900047; Thu, 20 Apr 2017 05:16:55 -0700 (PDT) Received: from localhost ([::1]:53623 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1B13-00024y-PR for importer@patchew.org; Thu, 20 Apr 2017 08:16:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38891) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amv-0007nb-IE for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Ami-00034b-PS for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:17 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34540) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Alz-0002UW-Ba; Thu, 20 Apr 2017 08:01:19 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 2CBA2341563; Thu, 20 Apr 2017 12:01:18 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w42002037; Thu, 20 Apr 2017 08:01:17 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 2CBA2341563 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 2CBA2341563 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:53 +0200 Message-Id: <20170420120058.28404-13-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 20 Apr 2017 12:01:18 +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] [PATCH 12/17] block: protect tracked_requests and flush_queue with reqs_lock 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block.c | 1 + block/io.c | 20 +++++++++++++++++--- include/block/block_int.h | 12 +++++++----- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index f1aec36..3b2ed29 100644 --- a/block.c +++ b/block.c @@ -234,6 +234,7 @@ BlockDriverState *bdrv_new(void) QLIST_INIT(&bs->op_blockers[i]); } notifier_with_return_list_init(&bs->before_write_notifiers); + qemu_co_mutex_init(&bs->reqs_lock); bs->refcnt =3D 1; bs->aio_context =3D qemu_get_aio_context(); =20 diff --git a/block/io.c b/block/io.c index d17564b..7af9d47 100644 --- a/block/io.c +++ b/block/io.c @@ -378,8 +378,10 @@ static void tracked_request_end(BdrvTrackedRequest *re= q) atomic_dec(&req->bs->serialising_in_flight); } =20 + qemu_co_mutex_lock(&req->bs->reqs_lock); QLIST_REMOVE(req, list); qemu_co_queue_restart_all(&req->wait_queue); + qemu_co_mutex_unlock(&req->bs->reqs_lock); } =20 /** @@ -404,7 +406,9 @@ static void tracked_request_begin(BdrvTrackedRequest *r= eq, =20 qemu_co_queue_init(&req->wait_queue); =20 + qemu_co_mutex_lock(&bs->reqs_lock); QLIST_INSERT_HEAD(&bs->tracked_requests, req, list); + qemu_co_mutex_unlock(&bs->reqs_lock); } =20 static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t ali= gn) @@ -526,6 +530,7 @@ static bool coroutine_fn wait_serialising_requests(Bdrv= TrackedRequest *self) =20 do { retry =3D false; + qemu_co_mutex_lock(&bs->reqs_lock); QLIST_FOREACH(req, &bs->tracked_requests, list) { if (req =3D=3D self || (!req->serialising && !self->serialisin= g)) { continue; @@ -544,7 +549,7 @@ static bool coroutine_fn wait_serialising_requests(Bdrv= TrackedRequest *self) * (instead of producing a deadlock in the former case). */ if (!req->waiting_for) { self->waiting_for =3D req; - qemu_co_queue_wait(&req->wait_queue, NULL); + qemu_co_queue_wait(&req->wait_queue, &bs->reqs_lock); self->waiting_for =3D NULL; retry =3D true; waited =3D true; @@ -552,6 +557,7 @@ static bool coroutine_fn wait_serialising_requests(Bdrv= TrackedRequest *self) } } } + qemu_co_mutex_unlock(&bs->reqs_lock); } while (retry); =20 return waited; @@ -2302,11 +2308,13 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) current_gen =3D atomic_read(&bs->write_gen); =20 /* Wait until any previous flushes are completed */ + qemu_co_mutex_lock(&bs->reqs_lock); while (bs->active_flush_req) { - qemu_co_queue_wait(&bs->flush_queue, NULL); + qemu_co_queue_wait(&bs->flush_queue, &bs->reqs_lock); } =20 bs->active_flush_req =3D true; + qemu_co_mutex_unlock(&bs->reqs_lock); =20 /* Write back all layers by calling one driver function */ if (bs->drv->bdrv_co_flush) { @@ -2328,10 +2336,14 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) goto flush_parent; } =20 - /* Check if we really need to flush anything */ + /* Check if we really need to flush anything + * TODO: use int and atomic access */ + qemu_co_mutex_lock(&bs->reqs_lock); if (bs->flushed_gen =3D=3D current_gen) { + qemu_co_mutex_unlock(&bs->reqs_lock); goto flush_parent; } + qemu_co_mutex_unlock(&bs->reqs_lock); =20 BLKDBG_EVENT(bs->file, BLKDBG_FLUSH_TO_DISK); if (bs->drv->bdrv_co_flush_to_disk) { @@ -2375,12 +2387,14 @@ flush_parent: ret =3D bs->file ? bdrv_co_flush(bs->file->bs) : 0; out: /* Notify any pending flushes that we have completed */ + qemu_co_mutex_lock(&bs->reqs_lock); if (ret =3D=3D 0) { bs->flushed_gen =3D current_gen; } bs->active_flush_req =3D false; /* Return value is ignored - it's ok if wait queue is empty */ qemu_co_queue_next(&bs->flush_queue); + qemu_co_mutex_unlock(&bs->reqs_lock); =20 early_exit: bdrv_dec_in_flight(bs); diff --git a/include/block/block_int.h b/include/block/block_int.h index 552680c..42b49f5 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -595,11 +595,6 @@ struct BlockDriverState { uint64_t write_threshold_offset; NotifierWithReturn write_threshold_notifier; =20 - QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; - CoQueue flush_queue; /* Serializing flush queue */ - bool active_flush_req; /* Flush request in flight? */ - unsigned int flushed_gen; /* Flushed write generation */ - QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps; =20 /* Offset after the highest byte written to */ @@ -630,6 +625,13 @@ struct BlockDriverState { /* Accessed with atomic ops. */ int quiesce_counter; unsigned int write_gen; /* Current data generation */ + + /* Protected by reqs_lock. */ + QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; + CoQueue flush_queue; /* Serializing flush queue */ + bool active_flush_req; /* Flush request in flight? */ + unsigned int flushed_gen; /* Flushed write generation */ + CoMutex reqs_lock; }; =20 struct BlockBackendRootState { --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492689851005661.8052447261733; Thu, 20 Apr 2017 05:04:11 -0700 (PDT) Received: from localhost ([::1]:53533 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Aoj-0000Yx-DP for importer@patchew.org; Thu, 20 Apr 2017 08:04:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38629) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Aml-0007am-QE for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Amf-00033G-Lt for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48738) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Am0-0002VP-PL; Thu, 20 Apr 2017 08:01:20 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 76B4D2EB640; Thu, 20 Apr 2017 12:01:19 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w43002037; Thu, 20 Apr 2017 08:01:18 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 76B4D2EB640 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 76B4D2EB640 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:54 +0200 Message-Id: <20170420120058.28404-14-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 20 Apr 2017 12:01:19 +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] [PATCH 13/17] coroutine-lock: introduce qemu_co_mutex_lock_unlock 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: qemu-block@nongnu.org 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" This primitive lets you lock/unlock a CoMutex, guaranteeing neither blocking nor cacheline bouncing if there is no qemu_co_mutex_lock critical section. Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi --- include/qemu/coroutine.h | 6 ++++++ util/qemu-coroutine-lock.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index a4509bd..8d4416c 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -157,6 +157,12 @@ void qemu_co_mutex_init(CoMutex *mutex); void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); =20 /** + * Locks the mutex and immediately unlock it. This is faster than back-to= -back + * lock/unlock if the mutex is not taken by anyone. + */ +void coroutine_fn qemu_co_mutex_lock_unlock(CoMutex *mutex); + +/** * Unlocks the mutex and schedules the next coroutine that was waiting for= this * lock to be run. */ diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c index 6328eed..86f56cd 100644 --- a/util/qemu-coroutine-lock.c +++ b/util/qemu-coroutine-lock.c @@ -287,6 +287,42 @@ retry_fast_path: self->locks_held++; } =20 +void coroutine_fn qemu_co_mutex_lock_unlock(CoMutex *mutex) +{ + AioContext *ctx =3D qemu_get_current_aio_context(); + int waiters, i; + +retry_fast_path: + waiters =3D atomic_read(&mutex->locked); + if (waiters =3D=3D 0) { + /* Provide same memory ordering semantics as mutex lock/unlock. */ + smp_mb_acquire(); + smp_mb_release(); + return; + } + + i =3D 0; + while (waiters =3D=3D 1 && ++i < 1000) { + if (atomic_read(&mutex->ctx) =3D=3D ctx) { + break; + } + waiters =3D atomic_read(&mutex->locked); + if (waiters =3D=3D 0) { + smp_mb_acquire(); + smp_mb_release(); + return; + } + cpu_relax(); + } + + if (atomic_cmpxchg(&mutex->locked, waiters, waiters + 1) !=3D waiters)= { + goto retry_fast_path; + } + + qemu_co_mutex_lock_slowpath(ctx, mutex); + qemu_co_mutex_unlock(mutex); +} + void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex) { Coroutine *self =3D qemu_coroutine_self(); --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690157426225.23265104186441; Thu, 20 Apr 2017 05:09:17 -0700 (PDT) Received: from localhost ([::1]:53562 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Atf-00050n-Fw for importer@patchew.org; Thu, 20 Apr 2017 08:09:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38742) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amp-0007gB-Re for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Amd-00032H-4U for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34622) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Am2-0002X3-5I; Thu, 20 Apr 2017 08:01:22 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 BB54E341577; Thu, 20 Apr 2017 12:01:20 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w44002037; Thu, 20 Apr 2017 08:01:19 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com BB54E341577 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com BB54E341577 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:55 +0200 Message-Id: <20170420120058.28404-15-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 20 Apr 2017 12:01:20 +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] [PATCH 14/17] block: optimize access to reqs_lock 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: qemu-block@nongnu.org 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" Hot path reqs_lock critical sections are very small; the only large critical sections happen when a request waits for serialising requests, and these should never happen in usual circumstances. We do not want these small critical sections to yield in any case, which calls for using a spinlock while writing the list. The reqs_lock is still used to protect the individual requests' CoQueue. For this purpose, serializing removals against concurrent walks of the request list can use lock_unlock for efficiency and determinism. The reqs_lock is also used to protect the flush generation counts, but that's unrelated. Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block.c | 1 + block/io.c | 25 ++++++++++++++++++++----- include/block/block_int.h | 11 ++++++++--- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index 3b2ed29..7ba6afe 100644 --- a/block.c +++ b/block.c @@ -234,6 +234,7 @@ BlockDriverState *bdrv_new(void) QLIST_INIT(&bs->op_blockers[i]); } notifier_with_return_list_init(&bs->before_write_notifiers); + qemu_spin_init(&bs->reqs_list_write_lock); qemu_co_mutex_init(&bs->reqs_lock); bs->refcnt =3D 1; bs->aio_context =3D qemu_get_aio_context(); diff --git a/block/io.c b/block/io.c index 7af9d47..476807d 100644 --- a/block/io.c +++ b/block/io.c @@ -374,14 +374,29 @@ void bdrv_drain_all(void) */ static void tracked_request_end(BdrvTrackedRequest *req) { + BlockDriverState *bs =3D req->bs; + if (req->serialising) { - atomic_dec(&req->bs->serialising_in_flight); + atomic_dec(&bs->serialising_in_flight); } =20 - qemu_co_mutex_lock(&req->bs->reqs_lock); + /* Note that there can be a concurrent visit while we remove the list, + * so we need to... + */ + qemu_spin_lock(&bs->reqs_list_write_lock); QLIST_REMOVE(req, list); + qemu_spin_unlock(&bs->reqs_list_write_lock); + + /* ... wait for it to end before we leave. qemu_co_mutex_lock_unlock + * avoids cacheline bouncing in the common case of no concurrent + * reader. + */ + qemu_co_mutex_lock_unlock(&bs->reqs_lock); + + /* Now no coroutine can add itself to the wait queue, so it is + * safe to call qemu_co_queue_restart_all outside the reqs_lock. + */ qemu_co_queue_restart_all(&req->wait_queue); - qemu_co_mutex_unlock(&req->bs->reqs_lock); } =20 /** @@ -406,9 +421,9 @@ static void tracked_request_begin(BdrvTrackedRequest *r= eq, =20 qemu_co_queue_init(&req->wait_queue); =20 - qemu_co_mutex_lock(&bs->reqs_lock); + qemu_spin_lock(&bs->reqs_list_write_lock); QLIST_INSERT_HEAD(&bs->tracked_requests, req, list); - qemu_co_mutex_unlock(&bs->reqs_lock); + qemu_spin_unlock(&bs->reqs_list_write_lock); } =20 static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t ali= gn) diff --git a/include/block/block_int.h b/include/block/block_int.h index 42b49f5..b298de8 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -78,9 +78,10 @@ typedef struct BdrvTrackedRequest { =20 QLIST_ENTRY(BdrvTrackedRequest) list; Coroutine *co; /* owner, used for deadlock detection */ - CoQueue wait_queue; /* coroutines blocked on this request */ - struct BdrvTrackedRequest *waiting_for; + + /* Protected by BlockDriverState's reqs_lock. */ + CoQueue wait_queue; /* coroutines blocked on this request */ } BdrvTrackedRequest; =20 struct BlockDriver { @@ -626,11 +627,15 @@ struct BlockDriverState { int quiesce_counter; unsigned int write_gen; /* Current data generation */ =20 - /* Protected by reqs_lock. */ + /* Writes are protected by reqs_list_write_lock. Reads take + * reqs_lock so that removals can easily synchronize with walks. + */ QLIST_HEAD(, BdrvTrackedRequest) tracked_requests; CoQueue flush_queue; /* Serializing flush queue */ bool active_flush_req; /* Flush request in flight? */ unsigned int flushed_gen; /* Flushed write generation */ + + QemuSpin reqs_list_write_lock; CoMutex reqs_lock; }; =20 --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690304644343.8158148876504; Thu, 20 Apr 2017 05:11:44 -0700 (PDT) Received: from localhost ([::1]:53583 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Aw2-00078f-RW for importer@patchew.org; Thu, 20 Apr 2017 08:11:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38745) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amq-0007ga-4n for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Ami-00034a-PY for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41376) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Am3-0002Ym-8L; Thu, 20 Apr 2017 08:01:23 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 2B43767EDD; Thu, 20 Apr 2017 12:01:22 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w45002037; Thu, 20 Apr 2017 08:01:21 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 2B43767EDD Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 2B43767EDD From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:56 +0200 Message-Id: <20170420120058.28404-16-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 20 Apr 2017 12:01:22 +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] [PATCH 15/17] block: introduce dirty_bitmap_mutex 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: qemu-block@nongnu.org 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" It protects only the list of dirty bitmaps; in the next patch we will also protect their content. Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block/dirty-bitmap.c | 51 +++++++++++++++++++++++++++++++++++++++++++= +++- block/mirror.c | 3 ++- blockdev.c | 44 +++++++--------------------------------- include/block/block_int.h | 5 +++++ migration/block.c | 6 ------ 5 files changed, 64 insertions(+), 45 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 519737c..e13718e 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -52,6 +52,24 @@ struct BdrvDirtyBitmapIter { BdrvDirtyBitmap *bitmap; }; =20 +static QemuMutex dirty_bitmap_mutex; + +static void __attribute__((__constructor__)) bdrv_dirty_bitmaps_init_lock(= void) +{ + qemu_mutex_init(&dirty_bitmap_mutex); +} + +static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs) +{ + qemu_mutex_lock(&dirty_bitmap_mutex); +} + +static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs) +{ + qemu_mutex_unlock(&dirty_bitmap_mutex); +} + +/* Called with BQL or dirty_bitmap lock taken. */ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *= name) { BdrvDirtyBitmap *bm; @@ -65,6 +83,7 @@ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState = *bs, const char *name) return NULL; } =20 +/* Called with BQL taken. */ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) { assert(!bdrv_dirty_bitmap_frozen(bitmap)); @@ -72,6 +91,7 @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) bitmap->name =3D NULL; } =20 +/* Called with BQL taken. */ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, uint32_t granularity, const char *name, @@ -100,7 +120,9 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverSt= ate *bs, bitmap->size =3D bitmap_size; bitmap->name =3D g_strdup(name); bitmap->disabled =3D false; + bdrv_dirty_bitmaps_lock(bs); QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list); + bdrv_dirty_bitmaps_unlock(bs); return bitmap; } =20 @@ -164,16 +186,19 @@ const char *bdrv_dirty_bitmap_name(const BdrvDirtyBit= map *bitmap) return bitmap->name; } =20 +/* Called with BQL taken. */ bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap) { return bitmap->successor; } =20 +/* Called with BQL taken. */ bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) { return !(bitmap->disabled || bitmap->successor); } =20 +/* Called with BQL taken. */ DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap) { if (bdrv_dirty_bitmap_frozen(bitmap)) { @@ -188,6 +213,7 @@ DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBit= map *bitmap) /** * Create a successor bitmap destined to replace this bitmap after an oper= ation. * Requires that the bitmap is not frozen and has no successor. + * Called with BQL taken. */ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, Error **er= rp) @@ -220,6 +246,7 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState= *bs, /** * For a bitmap with a successor, yield our name to the successor, * delete the old bitmap, and return a handle to the new bitmap. + * Called with BQL taken. */ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, @@ -247,6 +274,7 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriver= State *bs, * In cases of failure where we can no longer safely delete the parent, * we may wish to re-join the parent and child/successor. * The merged parent will be un-frozen, but not explicitly re-enabled. + * Called with BQL taken. */ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *parent, @@ -271,25 +299,30 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDrive= rState *bs, =20 /** * Truncates _all_ bitmaps attached to a BDS. + * Called with BQL taken. */ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs) { BdrvDirtyBitmap *bitmap; uint64_t size =3D bdrv_nb_sectors(bs); =20 + bdrv_dirty_bitmaps_lock(bs); QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { assert(!bdrv_dirty_bitmap_frozen(bitmap)); assert(!bitmap->active_iterators); hbitmap_truncate(bitmap->bitmap, size); bitmap->size =3D size; } + bdrv_dirty_bitmaps_unlock(bs); } =20 +/* Called with BQL taken. */ static void bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, bool only_named) { BdrvDirtyBitmap *bm, *next; + bdrv_dirty_bitmaps_lock(bs); QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { if ((!bitmap || bm =3D=3D bitmap) && (!only_named || bm->name)) { assert(!bm->active_iterators); @@ -301,15 +334,19 @@ static void bdrv_do_release_matching_dirty_bitmap(Blo= ckDriverState *bs, g_free(bm); =20 if (bitmap) { - return; + goto out; } } } if (bitmap) { abort(); } + +out: + bdrv_dirty_bitmaps_unlock(bs); } =20 +/* Called with BQL taken. */ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitm= ap) { bdrv_do_release_matching_dirty_bitmap(bs, bitmap, false); @@ -318,18 +355,21 @@ void bdrv_release_dirty_bitmap(BlockDriverState *bs, = BdrvDirtyBitmap *bitmap) /** * Release all named dirty bitmaps attached to a BDS (for use in bdrv_clos= e()). * There must not be any frozen bitmaps attached. + * Called with BQL taken. */ void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) { bdrv_do_release_matching_dirty_bitmap(bs, NULL, true); } =20 +/* Called with BQL taken. */ void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) { assert(!bdrv_dirty_bitmap_frozen(bitmap)); bitmap->disabled =3D true; } =20 +/* Called with BQL taken. */ void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) { assert(!bdrv_dirty_bitmap_frozen(bitmap)); @@ -342,6 +382,7 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDrive= rState *bs) BlockDirtyInfoList *list =3D NULL; BlockDirtyInfoList **plist =3D &list; =20 + bdrv_dirty_bitmaps_lock(bs); QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { BlockDirtyInfo *info =3D g_new0(BlockDirtyInfo, 1); BlockDirtyInfoList *entry =3D g_new0(BlockDirtyInfoList, 1); @@ -354,6 +395,7 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDrive= rState *bs) *plist =3D entry; plist =3D &entry->next; } + bdrv_dirty_bitmaps_unlock(bs); =20 return list; } @@ -508,12 +550,19 @@ void bdrv_set_dirty(BlockDriverState *bs, int64_t cur= _sector, int64_t nr_sectors) { BdrvDirtyBitmap *bitmap; + + if (QLIST_EMPTY(&bs->dirty_bitmaps)) { + return; + } + + bdrv_dirty_bitmaps_lock(bs); QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { if (!bdrv_dirty_bitmap_enabled(bitmap)) { continue; } hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); } + bdrv_dirty_bitmaps_unlock(bs); } =20 /** diff --git a/block/mirror.c b/block/mirror.c index 2e05dac..dc227a2 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -506,6 +506,8 @@ static void mirror_exit(BlockJob *job, void *opaque) BlockDriverState *mirror_top_bs =3D s->mirror_top_bs; Error *local_err =3D NULL; =20 + bdrv_release_dirty_bitmap(src, s->dirty_bitmap); + /* Make sure that the source BDS doesn't go away before we called * block_job_completed(). */ bdrv_ref(src); @@ -899,7 +901,6 @@ immediate_exit: g_free(s->cow_bitmap); g_free(s->in_flight_bitmap); bdrv_dirty_iter_free(s->dbi); - bdrv_release_dirty_bitmap(bs, s->dirty_bitmap); =20 data =3D g_malloc(sizeof(*data)); data->ret =3D ret; diff --git a/blockdev.c b/blockdev.c index e9b5717..09325f2 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1364,12 +1364,10 @@ out_aio_context: static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node, const char *name, BlockDriverState **pbs, - AioContext **paio, Error **errp) { BlockDriverState *bs; BdrvDirtyBitmap *bitmap; - AioContext *aio_context; =20 if (!node) { error_setg(errp, "Node cannot be NULL"); @@ -1385,29 +1383,17 @@ static BdrvDirtyBitmap *block_dirty_bitmap_lookup(c= onst char *node, return NULL; } =20 - aio_context =3D bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - bitmap =3D bdrv_find_dirty_bitmap(bs, name); if (!bitmap) { error_setg(errp, "Dirty bitmap '%s' not found", name); - goto fail; + return NULL; } =20 if (pbs) { *pbs =3D bs; } - if (paio) { - *paio =3D aio_context; - } else { - aio_context_release(aio_context); - } =20 return bitmap; - - fail: - aio_context_release(aio_context); - return NULL; } =20 /* New and old BlockDriverState structs for atomic group operations */ @@ -2024,7 +2010,6 @@ static void block_dirty_bitmap_clear_prepare(BlkActio= nState *common, state->bitmap =3D block_dirty_bitmap_lookup(action->node, action->name, &state->bs, - &state->aio_context, errp); if (!state->bitmap) { return; @@ -2733,7 +2718,6 @@ void qmp_block_dirty_bitmap_add(const char *node, con= st char *name, bool has_granularity, uint32_t granularity, Error **errp) { - AioContext *aio_context; BlockDriverState *bs; =20 if (!name || name[0] =3D=3D '\0') { @@ -2746,14 +2730,11 @@ void qmp_block_dirty_bitmap_add(const char *node, c= onst char *name, return; } =20 - aio_context =3D bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - if (has_granularity) { if (granularity < 512 || !is_power_of_2(granularity)) { error_setg(errp, "Granularity must be power of 2 " "and at least 512"); - goto out; + return; } } else { /* Default to cluster size, if available: */ @@ -2761,19 +2742,15 @@ void qmp_block_dirty_bitmap_add(const char *node, c= onst char *name, } =20 bdrv_create_dirty_bitmap(bs, granularity, name, errp); - - out: - aio_context_release(aio_context); } =20 void qmp_block_dirty_bitmap_remove(const char *node, const char *name, Error **errp) { - AioContext *aio_context; BlockDriverState *bs; BdrvDirtyBitmap *bitmap; =20 - bitmap =3D block_dirty_bitmap_lookup(node, name, &bs, &aio_context, er= rp); + bitmap =3D block_dirty_bitmap_lookup(node, name, &bs, errp); if (!bitmap || !bs) { return; } @@ -2782,13 +2759,10 @@ void qmp_block_dirty_bitmap_remove(const char *node= , const char *name, error_setg(errp, "Bitmap '%s' is currently frozen and cannot be removed", name); - goto out; + return; } bdrv_dirty_bitmap_make_anon(bitmap); bdrv_release_dirty_bitmap(bs, bitmap); - - out: - aio_context_release(aio_context); } =20 /** @@ -2798,11 +2772,10 @@ void qmp_block_dirty_bitmap_remove(const char *node= , const char *name, void qmp_block_dirty_bitmap_clear(const char *node, const char *name, Error **errp) { - AioContext *aio_context; BdrvDirtyBitmap *bitmap; BlockDriverState *bs; =20 - bitmap =3D block_dirty_bitmap_lookup(node, name, &bs, &aio_context, er= rp); + bitmap =3D block_dirty_bitmap_lookup(node, name, &bs, errp); if (!bitmap || !bs) { return; } @@ -2811,18 +2784,15 @@ void qmp_block_dirty_bitmap_clear(const char *node,= const char *name, error_setg(errp, "Bitmap '%s' is currently frozen and cannot be modified= ", name); - goto out; + return; } else if (!bdrv_dirty_bitmap_enabled(bitmap)) { error_setg(errp, "Bitmap '%s' is currently disabled and cannot be cleare= d", name); - goto out; + return; } =20 bdrv_clear_dirty_bitmap(bitmap, NULL); - - out: - aio_context_release(aio_context); } =20 void hmp_drive_del(Monitor *mon, const QDict *qdict) diff --git a/include/block/block_int.h b/include/block/block_int.h index b298de8..03db2cf 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -596,6 +596,11 @@ struct BlockDriverState { uint64_t write_threshold_offset; NotifierWithReturn write_threshold_notifier; =20 + /* Writing to the list requires the BQL _and_ the dirty_bitmap_mutex. + * Reading from the list can be done with either the BQL or the + * dirty_bitmap_mutex. Modifying a bitmap requires the AioContext + * lock. */ + QemuMutex dirty_bitmap_mutex; QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps; =20 /* Offset after the highest byte written to */ diff --git a/migration/block.c b/migration/block.c index 7734ff7..c33b522 100644 --- a/migration/block.c +++ b/migration/block.c @@ -346,10 +346,8 @@ static int set_dirty_tracking(void) int ret; =20 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { - aio_context_acquire(blk_get_aio_context(bmds->blk)); bmds->dirty_bitmap =3D bdrv_create_dirty_bitmap(blk_bs(bmds->blk), BLOCK_SIZE, NULL, NU= LL); - aio_context_release(blk_get_aio_context(bmds->blk)); if (!bmds->dirty_bitmap) { ret =3D -errno; goto fail; @@ -360,9 +358,7 @@ static int set_dirty_tracking(void) fail: QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { if (bmds->dirty_bitmap) { - aio_context_acquire(blk_get_aio_context(bmds->blk)); bdrv_release_dirty_bitmap(blk_bs(bmds->blk), bmds->dirty_bitma= p); - aio_context_release(blk_get_aio_context(bmds->blk)); } } return ret; @@ -375,9 +371,7 @@ static void unset_dirty_tracking(void) BlkMigDevState *bmds; =20 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) { - aio_context_acquire(blk_get_aio_context(bmds->blk)); bdrv_release_dirty_bitmap(blk_bs(bmds->blk), bmds->dirty_bitmap); - aio_context_release(blk_get_aio_context(bmds->blk)); } } =20 --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690264580439.0127695202618; Thu, 20 Apr 2017 05:11:04 -0700 (PDT) Received: from localhost ([::1]:53582 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1AvO-0006a4-NU for importer@patchew.org; Thu, 20 Apr 2017 08:11:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38747) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amq-0007gi-5W for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Ami-00034o-Ri for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43880) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Am4-0002bA-GC; Thu, 20 Apr 2017 08:01:24 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 6A4A1C7074; Thu, 20 Apr 2017 12:01:23 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w46002037; Thu, 20 Apr 2017 08:01:22 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6A4A1C7074 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 6A4A1C7074 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:57 +0200 Message-Id: <20170420120058.28404-17-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 20 Apr 2017 12:01:23 +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] [PATCH 16/17] block: protect modification of dirty bitmaps with a mutex 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: qemu-block@nongnu.org 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" Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block/dirty-bitmap.c | 74 ++++++++++++++++++++++++++++++++++++++++= +--- block/mirror.c | 11 +++++-- include/block/block_int.h | 4 +-- include/block/dirty-bitmap.h | 23 +++++++++++--- 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index e13718e..b854077 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -37,6 +37,7 @@ * or enabled. A frozen bitmap can only abdicate() or reclaim(). */ struct BdrvDirtyBitmap { + QemuMutex *mutex; HBitmap *bitmap; /* Dirty sector bitmap implementation */ HBitmap *meta; /* Meta dirty bitmap */ BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status = */ @@ -69,6 +70,16 @@ static inline void bdrv_dirty_bitmaps_unlock(BlockDriver= State *bs) qemu_mutex_unlock(&dirty_bitmap_mutex); } =20 +void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap) +{ + qemu_mutex_lock(bitmap->mutex); +} + +void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap) +{ + qemu_mutex_unlock(bitmap->mutex); +} + /* Called with BQL or dirty_bitmap lock taken. */ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *= name) { @@ -116,6 +127,7 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverSt= ate *bs, return NULL; } bitmap =3D g_new0(BdrvDirtyBitmap, 1); + bitmap->mutex =3D &bs->dirty_bitmap_mutex; bitmap->bitmap =3D hbitmap_alloc(bitmap_size, ctz32(sector_granularity= )); bitmap->size =3D bitmap_size; bitmap->name =3D g_strdup(name); @@ -141,18 +153,22 @@ void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *b= itmap, int chunk_size) { assert(!bitmap->meta); + qemu_mutex_lock(bitmap->mutex); bitmap->meta =3D hbitmap_create_meta(bitmap->bitmap, chunk_size * BITS_PER_BYTE); + qemu_mutex_unlock(bitmap->mutex); } =20 void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap) { assert(bitmap->meta); + qemu_mutex_lock(bitmap->mutex); hbitmap_free_meta(bitmap->bitmap); bitmap->meta =3D NULL; + qemu_mutex_unlock(bitmap->mutex); } =20 -int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs, +int bdrv_dirty_bitmap_get_meta_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector, int nb_sectors) { @@ -169,11 +185,26 @@ int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs, return false; } =20 +int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, int64_t sector, + int nb_sectors) +{ + bool dirty; + + qemu_mutex_lock(bitmap->mutex); + dirty =3D bdrv_dirty_bitmap_get_meta_locked(bs, bitmap, sector, nb_sec= tors); + qemu_mutex_unlock(bitmap->mutex); + + return dirty; +} + void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector, int nb_sectors) { + qemu_mutex_lock(bitmap->mutex); hbitmap_reset(bitmap->meta, sector, nb_sectors); + qemu_mutex_unlock(bitmap->mutex); } =20 int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap) @@ -400,7 +431,8 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDrive= rState *bs) return list; } =20 -int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, +/* Called within bdrv_dirty_bitmap_lock..unlock */ +int bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector) { if (bitmap) { @@ -410,6 +442,18 @@ int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitm= ap *bitmap, } } =20 +int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, + int64_t sector) +{ + bool dirty; + + bdrv_dirty_bitmap_lock(bitmap); + dirty =3D bdrv_get_dirty_locked(bs, bitmap, sector); + bdrv_dirty_bitmap_unlock(bitmap); + + return dirty; +} + /** * Chooses a default granularity based on the existing cluster size, * but clamped between [4K, 64K]. Defaults to 64K in the case that there @@ -474,23 +518,42 @@ int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *ite= r) return hbitmap_iter_next(&iter->hbi); } =20 +/* Called within bdrv_dirty_bitmap_lock..unlock */ +void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, + int64_t cur_sector, int64_t nr_sectors) +{ + assert(bdrv_dirty_bitmap_enabled(bitmap)); + hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); +} + void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors) { + bdrv_dirty_bitmap_lock(bitmap); + bdrv_set_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors); + bdrv_dirty_bitmap_unlock(bitmap); +} + +/* Called within bdrv_dirty_bitmap_lock..unlock */ +void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, + int64_t cur_sector, int64_t nr_sectors) +{ assert(bdrv_dirty_bitmap_enabled(bitmap)); - hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); + hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors); } =20 void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors) { - assert(bdrv_dirty_bitmap_enabled(bitmap)); - hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors); + bdrv_dirty_bitmap_lock(bitmap); + bdrv_reset_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors); + bdrv_dirty_bitmap_unlock(bitmap); } =20 void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) { assert(bdrv_dirty_bitmap_enabled(bitmap)); + bdrv_dirty_bitmap_lock(bitmap); if (!out) { hbitmap_reset_all(bitmap->bitmap); } else { @@ -499,6 +562,7 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, H= Bitmap **out) hbitmap_granularity(backup)); *out =3D backup; } + bdrv_dirty_bitmap_unlock(bitmap); } =20 void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in) diff --git a/block/mirror.c b/block/mirror.c index dc227a2..6a5b0f8 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -344,10 +344,12 @@ static uint64_t coroutine_fn mirror_iteration(MirrorB= lockJob *s) =20 sector_num =3D bdrv_dirty_iter_next(s->dbi); if (sector_num < 0) { + bdrv_dirty_bitmap_lock(s->dirty_bitmap); bdrv_set_dirty_iter(s->dbi, 0); sector_num =3D bdrv_dirty_iter_next(s->dbi); trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap)= ); assert(sector_num >=3D 0); + bdrv_dirty_bitmap_unlock(s->dirty_bitmap); } =20 first_chunk =3D sector_num / sectors_per_chunk; @@ -360,12 +362,13 @@ static uint64_t coroutine_fn mirror_iteration(MirrorB= lockJob *s) =20 /* Find the number of consective dirty chunks following the first dirty * one, and wait for in flight requests in them. */ + bdrv_dirty_bitmap_lock(s->dirty_bitmap); while (nb_chunks * sectors_per_chunk < (s->buf_size >> BDRV_SECTOR_BIT= S)) { int64_t next_dirty; int64_t next_sector =3D sector_num + nb_chunks * sectors_per_chunk; int64_t next_chunk =3D next_sector / sectors_per_chunk; if (next_sector >=3D end || - !bdrv_get_dirty(source, s->dirty_bitmap, next_sector)) { + !bdrv_get_dirty_locked(source, s->dirty_bitmap, next_sector)) { break; } if (test_bit(next_chunk, s->in_flight_bitmap)) { @@ -386,8 +389,10 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBl= ockJob *s) * calling bdrv_get_block_status_above could yield - if some blocks are * marked dirty in this window, we need to know. */ - bdrv_reset_dirty_bitmap(s->dirty_bitmap, sector_num, - nb_chunks * sectors_per_chunk); + bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, sector_num, + nb_chunks * sectors_per_chunk); + bdrv_dirty_bitmap_unlock(s->dirty_bitmap); + bitmap_set(s->in_flight_bitmap, sector_num / sectors_per_chunk, nb_chu= nks); while (nb_chunks > 0 && sector_num < end) { int64_t ret; diff --git a/include/block/block_int.h b/include/block/block_int.h index 03db2cf..c264ead 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -598,8 +598,8 @@ struct BlockDriverState { =20 /* Writing to the list requires the BQL _and_ the dirty_bitmap_mutex. * Reading from the list can be done with either the BQL or the - * dirty_bitmap_mutex. Modifying a bitmap requires the AioContext - * lock. */ + * dirty_bitmap_mutex. Modifying a bitmap only requires + * dirty_bitmap_mutex. */ QemuMutex dirty_bitmap_mutex; QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps; =20 diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index 9dea14b..b6fc35b 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -45,6 +45,9 @@ void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector, int nb_sectors); +int bdrv_dirty_bitmap_get_meta_locked(BlockDriverState *bs, + BdrvDirtyBitmap *bitmap, int64_t sec= tor, + int nb_sectors); void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, int64_t sector, int nb_sectors); @@ -52,11 +55,6 @@ BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyB= itmap *bitmap); BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap, uint64_t first_sector); void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter); -int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter); -void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t sector_num); -int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); -int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap); -void bdrv_dirty_bitmap_truncate(BlockDriverState *bs); =20 uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitma= p, uint64_t start, uint64_t cou= nt); @@ -72,4 +70,19 @@ void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitma= p *bitmap, bool finish); void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap); =20 +/* Functions that require manual locking. */ +void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap); +void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap); +int bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, + int64_t sector); +void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, + int64_t cur_sector, int64_t nr_sectors); +void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, + int64_t cur_sector, int64_t nr_sectors= ); +int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter); +void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t sector_num); +int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); +int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap); +void bdrv_dirty_bitmap_truncate(BlockDriverState *bs); + #endif --=20 2.9.3 From nobody Fri May 3 19:51:13 2024 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 1492690420833790.0151784082418; Thu, 20 Apr 2017 05:13:40 -0700 (PDT) Received: from localhost ([::1]:53604 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Axv-0000GB-AB for importer@patchew.org; Thu, 20 Apr 2017 08:13:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38746) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d1Amq-0007gh-5N for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d1Amk-00035N-LV for qemu-devel@nongnu.org; Thu, 20 Apr 2017 08:02:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41438) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d1Am5-0002cq-Kn; Thu, 20 Apr 2017 08:01:25 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (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 883BE67EDF; Thu, 20 Apr 2017 12:01:24 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-9.ams2.redhat.com [10.36.117.9]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v3KC0w47002037; Thu, 20 Apr 2017 08:01:23 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 883BE67EDF Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=pbonzini@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 883BE67EDF From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 20 Apr 2017 14:00:58 +0200 Message-Id: <20170420120058.28404-18-pbonzini@redhat.com> In-Reply-To: <20170420120058.28404-1-pbonzini@redhat.com> References: <20170420120058.28404-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 20 Apr 2017 12:01:24 +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] [PATCH 17/17] block: make accounting thread-safe 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: qemu-block@nongnu.org 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" I'm not trying too hard yet. Later, with multiqueue support, this may cause cacheline bouncing. Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng --- block/accounting.c | 15 +++++++++++++++ include/block/accounting.h | 8 ++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/block/accounting.c b/block/accounting.c index 3f457c4..dc10855 100644 --- a/block/accounting.c +++ b/block/accounting.c @@ -35,6 +35,7 @@ static const int qtest_latency_ns =3D NANOSECONDS_PER_SEC= OND / 1000; void block_acct_init(BlockAcctStats *stats, bool account_invalid, bool account_failed) { + qemu_spin_init(&stats->spin); stats->account_invalid =3D account_invalid; stats->account_failed =3D account_failed; =20 @@ -58,12 +59,15 @@ void block_acct_add_interval(BlockAcctStats *stats, uns= igned interval_length) =20 s =3D g_new0(BlockAcctTimedStats, 1); s->interval_length =3D interval_length; + s->stats =3D stats; + qemu_spin_lock(&stats->spin); QSLIST_INSERT_HEAD(&stats->intervals, s, entries); =20 for (i =3D 0; i < BLOCK_MAX_IOTYPE; i++) { timed_average_init(&s->latency[i], clock_type, (uint64_t) interval_length * NANOSECONDS_PER_SE= COND); } + qemu_spin_unlock(&stats->spin); } =20 BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats, @@ -98,6 +102,7 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCoo= kie *cookie) =20 assert(cookie->type < BLOCK_MAX_IOTYPE); =20 + qemu_spin_lock(&stats->spin); stats->nr_bytes[cookie->type] +=3D cookie->bytes; stats->nr_ops[cookie->type]++; stats->total_time_ns[cookie->type] +=3D latency_ns; @@ -106,12 +111,14 @@ void block_acct_done(BlockAcctStats *stats, BlockAcct= Cookie *cookie) QSLIST_FOREACH(s, &stats->intervals, entries) { timed_average_account(&s->latency[cookie->type], latency_ns); } + qemu_spin_unlock(&stats->spin); } =20 void block_acct_failed(BlockAcctStats *stats, BlockAcctCookie *cookie) { assert(cookie->type < BLOCK_MAX_IOTYPE); =20 + qemu_spin_lock(&stats->spin); stats->failed_ops[cookie->type]++; =20 if (stats->account_failed) { @@ -130,6 +137,7 @@ void block_acct_failed(BlockAcctStats *stats, BlockAcct= Cookie *cookie) timed_average_account(&s->latency[cookie->type], latency_ns); } } + qemu_spin_unlock(&stats->spin); } =20 void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type) @@ -141,18 +149,23 @@ void block_acct_invalid(BlockAcctStats *stats, enum B= lockAcctType type) * invalid requests are accounted during their submission, * therefore there's no actual I/O involved. */ =20 + qemu_spin_lock(&stats->spin); stats->invalid_ops[type]++; =20 if (stats->account_invalid) { stats->last_access_time_ns =3D qemu_clock_get_ns(clock_type); } + qemu_spin_unlock(&stats->spin); } =20 void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type, int num_requests) { assert(type < BLOCK_MAX_IOTYPE); + + qemu_spin_lock(&stats->spin); stats->merged[type] +=3D num_requests; + qemu_spin_unlock(&stats->spin); } =20 int64_t block_acct_idle_time_ns(BlockAcctStats *stats) @@ -167,7 +180,9 @@ double block_acct_queue_depth(BlockAcctTimedStats *stat= s, =20 assert(type < BLOCK_MAX_IOTYPE); =20 + qemu_spin_lock(&stats->stats->spin); sum =3D timed_average_sum(&stats->latency[type], &elapsed); + qemu_spin_unlock(&stats->stats->spin); =20 return (double) sum / elapsed; } diff --git a/include/block/accounting.h b/include/block/accounting.h index 2089163..90b7a1d 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -26,8 +26,10 @@ #define BLOCK_ACCOUNTING_H =20 #include "qemu/timed-average.h" +#include "qemu/thread.h" =20 typedef struct BlockAcctTimedStats BlockAcctTimedStats; +typedef struct BlockAcctStats BlockAcctStats; =20 enum BlockAcctType { BLOCK_ACCT_READ, @@ -37,12 +39,14 @@ enum BlockAcctType { }; =20 struct BlockAcctTimedStats { + BlockAcctStats *stats; TimedAverage latency[BLOCK_MAX_IOTYPE]; unsigned interval_length; /* in seconds */ QSLIST_ENTRY(BlockAcctTimedStats) entries; }; =20 -typedef struct BlockAcctStats { +struct BlockAcctStats { + QemuSpin spin; uint64_t nr_bytes[BLOCK_MAX_IOTYPE]; uint64_t nr_ops[BLOCK_MAX_IOTYPE]; uint64_t invalid_ops[BLOCK_MAX_IOTYPE]; @@ -53,7 +57,7 @@ typedef struct BlockAcctStats { QSLIST_HEAD(, BlockAcctTimedStats) intervals; bool account_invalid; bool account_failed; -} BlockAcctStats; +}; =20 typedef struct BlockAcctCookie { int64_t bytes; --=20 2.9.3