From nobody Sun Feb 8 13:10:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1623656176696297.19098708586193; Mon, 14 Jun 2021 00:36:16 -0700 (PDT) Received: from localhost ([::1]:38440 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lsh8p-0000GU-Ic for importer@patchew.org; Mon, 14 Jun 2021 03:36:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35120) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6l-0005SZ-EV for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:07 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:55749) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6j-0004xB-T8 for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:07 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-543-VNaD8g_kPvOouX5GXhfPmw-1; Mon, 14 Jun 2021 03:34:02 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D833F100C660; Mon, 14 Jun 2021 07:34:00 +0000 (UTC) Received: from localhost.localdomain (ovpn-113-49.ams2.redhat.com [10.36.113.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id 79B4E5D6A8; Mon, 14 Jun 2021 07:33:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623656045; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XJskv7PwmFtVED6joTZIFTWoa8EePTwK/hxu88B8IHc=; b=HQGAFR8lnUgwHuc33IEd2xU4VAjEGt58vsBqTw65L3YQUFFOI16ZE4aQu7OpGZqohguh03 1Nh99Q8CKqKvN70uQMz13vuufsmYFznuYvuW10m7cM+uyUyq4lOpSkuR13BtqLdKt24AYs Jdrr4NH3f8+EZk3alVFAM3wgsByfz7g= X-MC-Unique: VNaD8g_kPvOouX5GXhfPmw-1 From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [PATCH v4 1/6] block-copy: small refactor in block_copy_task_entry and block_copy_common Date: Mon, 14 Jun 2021 09:33:45 +0200 Message-Id: <20210614073350.17048-2-eesposit@redhat.com> In-Reply-To: <20210614073350.17048-1-eesposit@redhat.com> References: <20210614073350.17048-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eesposit@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -29 X-Spam_score: -3.0 X-Spam_bar: --- X-Spam_report: (-3.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.199, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Emanuele Giuseppe Esposito , Vladimir Sementsov-Ogievskiy , qemu-devel@nongnu.org, Max Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Use a local variable instead of referencing BlockCopyState through a BlockCopyCallState or BlockCopyTask every time. This is in preparation for next patches. No functional change intended. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy --- block/block-copy.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index 943e30b7e6..f0dbb4912b 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -452,14 +452,15 @@ static void block_copy_handle_copy_range_result(Block= CopyState *s, static coroutine_fn int block_copy_task_entry(AioTask *task) { BlockCopyTask *t =3D container_of(task, BlockCopyTask, task); + BlockCopyState *s =3D t->s; bool error_is_read =3D false; bool copy_range =3D t->copy_range; int ret; =20 - ret =3D block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes, + ret =3D block_copy_do_copy(s, t->offset, t->bytes, t->zeroes, ©_range, &error_is_read); if (t->copy_range) { - block_copy_handle_copy_range_result(t->s, copy_range); + block_copy_handle_copy_range_result(s, copy_range); } if (ret < 0) { if (!t->call_state->ret) { @@ -467,9 +468,9 @@ static coroutine_fn int block_copy_task_entry(AioTask *= task) t->call_state->error_is_read =3D error_is_read; } } else { - progress_work_done(t->s->progress, t->bytes); + progress_work_done(s->progress, t->bytes); } - co_put_to_shres(t->s->mem, t->bytes); + co_put_to_shres(s->mem, t->bytes); block_copy_task_end(t, ret); =20 return ret; @@ -714,14 +715,15 @@ void block_copy_kick(BlockCopyCallState *call_state) static int coroutine_fn block_copy_common(BlockCopyCallState *call_state) { int ret; + BlockCopyState *s =3D call_state->s; =20 - QLIST_INSERT_HEAD(&call_state->s->calls, call_state, list); + QLIST_INSERT_HEAD(&s->calls, call_state, list); =20 do { ret =3D block_copy_dirty_clusters(call_state); =20 if (ret =3D=3D 0 && !call_state->cancelled) { - ret =3D block_copy_wait_one(call_state->s, call_state->offset, + ret =3D block_copy_wait_one(s, call_state->offset, call_state->bytes); } =20 --=20 2.31.1 From nobody Sun Feb 8 13:10:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1623656178691374.7743991135411; Mon, 14 Jun 2021 00:36:18 -0700 (PDT) Received: from localhost ([::1]:38542 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lsh8r-0000LQ-JR for importer@patchew.org; Mon, 14 Jun 2021 03:36:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35132) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6n-0005Ss-E3 for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:41177) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6k-0004yG-Rs for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:09 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-22-_m7E2ZwgNDGdXIdJ-bR79g-1; Mon, 14 Jun 2021 03:34:04 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9DDB9C73A3; Mon, 14 Jun 2021 07:34:03 +0000 (UTC) Received: from localhost.localdomain (ovpn-113-49.ams2.redhat.com [10.36.113.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3FEEC5D6A8; Mon, 14 Jun 2021 07:34:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623656046; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EvdNo2jN1RTKp8NL2EIbvTOSqp1wlOQAcn+JbkB17J4=; b=cmPiR+1kLv1fEn5sw1xgrx6tWV0+OItcyFnynFdVAvb2gSzIg9vl1e4MuXHtM7XxyxlYdw JfrQWuyCl/PkFWcoOqkpediRoipwLkjaQ+qfJA6+vQLzi91wbIxOkJkKxuKuufb6Fuus9b bAis8pbHE1QMYpn2to2HcAlYPKFbuKc= X-MC-Unique: _m7E2ZwgNDGdXIdJ-bR79g-1 From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [PATCH v4 2/6] block-copy: streamline choice of copy_range vs. read/write Date: Mon, 14 Jun 2021 09:33:46 +0200 Message-Id: <20210614073350.17048-3-eesposit@redhat.com> In-Reply-To: <20210614073350.17048-1-eesposit@redhat.com> References: <20210614073350.17048-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eesposit@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -29 X-Spam_score: -3.0 X-Spam_bar: --- X-Spam_report: (-3.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.199, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Emanuele Giuseppe Esposito , Vladimir Sementsov-Ogievskiy , qemu-devel@nongnu.org, Max Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Paolo Bonzini Put the logic to determine the copy size in a separate function, so that there is a simple state machine for the possible methods of copying data from one BlockDriverState to the other. Use .method instead of .copy_range as in-out argument, and include also .zeroes as an additional copy method. While at it, store the common computation of block_copy_max_transfer into a new field of BlockCopyState, and make sure that we always obey max_transfer; that's more efficient even for the COPY_RANGE_READ_WRITE case. Signed-off-by: Emanuele Giuseppe Esposito Signed-off-by: Paolo Bonzini Reviewed-by: Vladimir Sementsov-Ogievskiy --- block/block-copy.c | 174 +++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 85 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index f0dbb4912b..3f26be8ddc 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -28,6 +28,14 @@ #define BLOCK_COPY_MAX_WORKERS 64 #define BLOCK_COPY_SLICE_TIME 100000000ULL /* ns */ =20 +typedef enum { + COPY_READ_WRITE_CLUSTER, + COPY_READ_WRITE, + COPY_WRITE_ZEROES, + COPY_RANGE_SMALL, + COPY_RANGE_FULL +} BlockCopyMethod; + static coroutine_fn int block_copy_task_entry(AioTask *task); =20 typedef struct BlockCopyCallState { @@ -64,8 +72,7 @@ typedef struct BlockCopyTask { BlockCopyCallState *call_state; int64_t offset; int64_t bytes; - bool zeroes; - bool copy_range; + BlockCopyMethod method; QLIST_ENTRY(BlockCopyTask) list; CoQueue wait_queue; /* coroutines blocked on this task */ } BlockCopyTask; @@ -86,8 +93,8 @@ typedef struct BlockCopyState { BdrvDirtyBitmap *copy_bitmap; int64_t in_flight_bytes; int64_t cluster_size; - bool use_copy_range; - int64_t copy_size; + BlockCopyMethod method; + int64_t max_transfer; uint64_t len; QLIST_HEAD(, BlockCopyTask) tasks; /* All tasks from all block-copy ca= lls */ QLIST_HEAD(, BlockCopyCallState) calls; @@ -149,6 +156,24 @@ static bool coroutine_fn block_copy_wait_one(BlockCopy= State *s, int64_t offset, return true; } =20 +static int64_t block_copy_chunk_size(BlockCopyState *s) +{ + switch (s->method) { + case COPY_READ_WRITE_CLUSTER: + return s->cluster_size; + case COPY_READ_WRITE: + case COPY_RANGE_SMALL: + return MIN(MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER), + s->max_transfer); + case COPY_RANGE_FULL: + return MIN(MAX(s->cluster_size, BLOCK_COPY_MAX_COPY_RANGE), + s->max_transfer); + default: + /* Cannot have COPY_WRITE_ZEROES here. */ + abort(); + } +} + /* * Search for the first dirty area in offset/bytes range and create task at * the beginning of it. @@ -158,8 +183,9 @@ static BlockCopyTask *block_copy_task_create(BlockCopyS= tate *s, int64_t offset, int64_t bytes) { BlockCopyTask *task; - int64_t max_chunk =3D MIN_NON_ZERO(s->copy_size, call_state->max_chunk= ); + int64_t max_chunk =3D block_copy_chunk_size(s); =20 + max_chunk =3D MIN_NON_ZERO(max_chunk, call_state->max_chunk); if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap, offset, offset + bytes, max_chunk, &offset, &bytes)) @@ -183,7 +209,7 @@ static BlockCopyTask *block_copy_task_create(BlockCopyS= tate *s, .call_state =3D call_state, .offset =3D offset, .bytes =3D bytes, - .copy_range =3D s->use_copy_range, + .method =3D s->method, }; qemu_co_queue_init(&task->wait_queue); QLIST_INSERT_HEAD(&s->tasks, task, list); @@ -267,28 +293,28 @@ BlockCopyState *block_copy_state_new(BdrvChild *sourc= e, BdrvChild *target, .len =3D bdrv_dirty_bitmap_size(copy_bitmap), .write_flags =3D write_flags, .mem =3D shres_create(BLOCK_COPY_MAX_MEM), + .max_transfer =3D QEMU_ALIGN_DOWN( + block_copy_max_transfer(source, target= ), + cluster_size), }; =20 - if (block_copy_max_transfer(source, target) < cluster_size) { + if (s->max_transfer < cluster_size) { /* * copy_range does not respect max_transfer. We don't want to both= er * with requests smaller than block-copy cluster size, so fallback= to * buffered copying (read and write respect max_transfer on their * behalf). */ - s->use_copy_range =3D false; - s->copy_size =3D cluster_size; + s->method =3D COPY_READ_WRITE_CLUSTER; } else if (write_flags & BDRV_REQ_WRITE_COMPRESSED) { /* Compression supports only cluster-size writes and no copy-range= . */ - s->use_copy_range =3D false; - s->copy_size =3D cluster_size; + s->method =3D COPY_READ_WRITE_CLUSTER; } else { /* * We enable copy-range, but keep small copy_size, until first * successful copy_range (look at block_copy_do_copy). */ - s->use_copy_range =3D use_copy_range; - s->copy_size =3D MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER); + s->method =3D use_copy_range ? COPY_RANGE_SMALL : COPY_READ_WRITE; } =20 ratelimit_init(&s->rate_limit); @@ -343,17 +369,14 @@ static coroutine_fn int block_copy_task_run(AioTaskPo= ol *pool, * * No sync here: nor bitmap neighter intersecting requests handling, only = copy. * - * @copy_range is an in-out argument: if *copy_range is false, copy_range = is not - * done. If *copy_range is true, copy_range is attempted. If the copy_range - * attempt fails, the function falls back to the usual read+write and - * *copy_range is set to false. *copy_range and zeroes must not be true - * simultaneously. - * + * @method is an in-out argument, so that copy_range can be either extende= d to + * a full-size buffer or disabled if the copy_range attempt fails. The ou= tput + * value of @method should be used for subsequent tasks. * Returns 0 on success. */ static int coroutine_fn block_copy_do_copy(BlockCopyState *s, int64_t offset, int64_t bytes, - bool zeroes, bool *copy_range, + BlockCopyMethod *method, bool *error_is_read) { int ret; @@ -367,9 +390,9 @@ static int coroutine_fn block_copy_do_copy(BlockCopySta= te *s, assert(offset + bytes <=3D s->len || offset + bytes =3D=3D QEMU_ALIGN_UP(s->len, s->cluster_size)); assert(nbytes < INT_MAX); - assert(!(*copy_range && zeroes)); =20 - if (zeroes) { + switch (*method) { + case COPY_WRITE_ZEROES: ret =3D bdrv_co_pwrite_zeroes(s->target, offset, nbytes, s->write_= flags & ~BDRV_REQ_WRITE_COMPRESSED); if (ret < 0) { @@ -377,76 +400,59 @@ static int coroutine_fn block_copy_do_copy(BlockCopyS= tate *s, *error_is_read =3D false; } return ret; - } =20 - if (*copy_range) { + case COPY_RANGE_SMALL: + case COPY_RANGE_FULL: ret =3D bdrv_co_copy_range(s->source, offset, s->target, offset, n= bytes, 0, s->write_flags); - if (ret < 0) { - trace_block_copy_copy_range_fail(s, offset, ret); - *copy_range =3D false; - /* Fallback to read+write with allocated buffer */ - } else { + if (ret >=3D 0) { + /* Successful copy-range, increase copy_size. */ + *method =3D COPY_RANGE_FULL; return 0; } - } =20 - /* - * In case of failed copy_range request above, we may proceed with buf= fered - * request larger than BLOCK_COPY_MAX_BUFFER. Still, further requests = will - * be properly limited, so don't care too much. Moreover the most like= ly - * case (copy_range is unsupported for the configuration, so the very = first - * copy_range request fails) is handled by setting large copy_size only - * after first successful copy_range. - */ + trace_block_copy_copy_range_fail(s, offset, ret); + *method =3D COPY_READ_WRITE; + /* Fall through to read+write with allocated buffer */ =20 - bounce_buffer =3D qemu_blockalign(s->source->bs, nbytes); + case COPY_READ_WRITE_CLUSTER: + case COPY_READ_WRITE: + /* + * In case of failed copy_range request above, we may proceed with + * buffered request larger than BLOCK_COPY_MAX_BUFFER. + * Still, further requests will be properly limited, so don't care= too + * much. Moreover the most likely case (copy_range is unsupported = for + * the configuration, so the very first copy_range request fails) + * is handled by setting large copy_size only after first successf= ul + * copy_range. + */ =20 - ret =3D bdrv_co_pread(s->source, offset, nbytes, bounce_buffer, 0); - if (ret < 0) { - trace_block_copy_read_fail(s, offset, ret); - *error_is_read =3D true; - goto out; - } + bounce_buffer =3D qemu_blockalign(s->source->bs, nbytes); =20 - ret =3D bdrv_co_pwrite(s->target, offset, nbytes, bounce_buffer, - s->write_flags); - if (ret < 0) { - trace_block_copy_write_fail(s, offset, ret); - *error_is_read =3D false; - goto out; - } + ret =3D bdrv_co_pread(s->source, offset, nbytes, bounce_buffer, 0); + if (ret < 0) { + trace_block_copy_read_fail(s, offset, ret); + *error_is_read =3D true; + goto out; + } =20 -out: - qemu_vfree(bounce_buffer); + ret =3D bdrv_co_pwrite(s->target, offset, nbytes, bounce_buffer, + s->write_flags); + if (ret < 0) { + trace_block_copy_write_fail(s, offset, ret); + *error_is_read =3D false; + goto out; + } =20 - return ret; -} + out: + qemu_vfree(bounce_buffer); + break; =20 -static void block_copy_handle_copy_range_result(BlockCopyState *s, - bool is_success) -{ - if (!s->use_copy_range) { - /* already disabled */ - return; + default: + abort(); } =20 - if (is_success) { - /* - * Successful copy-range. Now increase copy_size. copy_range - * does not respect max_transfer (it's a TODO), so we factor - * that in here. - */ - s->copy_size =3D - MIN(MAX(s->cluster_size, BLOCK_COPY_MAX_COPY_RANGE), - QEMU_ALIGN_DOWN(block_copy_max_transfer(s->source, - s->target), - s->cluster_size)); - } else { - /* Copy-range failed, disable it. */ - s->use_copy_range =3D false; - s->copy_size =3D MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER); - } + return ret; } =20 static coroutine_fn int block_copy_task_entry(AioTask *task) @@ -454,13 +460,12 @@ static coroutine_fn int block_copy_task_entry(AioTask= *task) BlockCopyTask *t =3D container_of(task, BlockCopyTask, task); BlockCopyState *s =3D t->s; bool error_is_read =3D false; - bool copy_range =3D t->copy_range; + BlockCopyMethod method =3D t->method; int ret; =20 - ret =3D block_copy_do_copy(s, t->offset, t->bytes, t->zeroes, - ©_range, &error_is_read); - if (t->copy_range) { - block_copy_handle_copy_range_result(s, copy_range); + ret =3D block_copy_do_copy(s, t->offset, t->bytes, &method, &error_is_= read); + if (s->method =3D=3D t->method) { + s->method =3D method; } if (ret < 0) { if (!t->call_state->ret) { @@ -643,8 +648,7 @@ block_copy_dirty_clusters(BlockCopyCallState *call_stat= e) continue; } if (ret & BDRV_BLOCK_ZERO) { - task->zeroes =3D true; - task->copy_range =3D false; + task->method =3D COPY_WRITE_ZEROES; } =20 if (!call_state->ignore_ratelimit) { --=20 2.31.1 From nobody Sun Feb 8 13:10:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1623656300662975.3365779716113; Mon, 14 Jun 2021 00:38:20 -0700 (PDT) Received: from localhost ([::1]:45490 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lshAp-0004xf-KC for importer@patchew.org; Mon, 14 Jun 2021 03:38:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35156) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6p-0005TK-Gq for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:11 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:51394) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6n-00050q-Oq for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:11 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-55-rEarg_nDMfG2T6YlCS6yKg-1; Mon, 14 Jun 2021 03:34:07 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 342B8801B12; Mon, 14 Jun 2021 07:34:06 +0000 (UTC) Received: from localhost.localdomain (ovpn-113-49.ams2.redhat.com [10.36.113.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id 06C335D6A8; Mon, 14 Jun 2021 07:34:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623656049; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a0yBKFUnJ6gm9juDmQZ0BG1B0182SN0G6yJKuisoo7k=; b=eJa2ByMff24NTRBhogrIKF8veN19SLbhM+AxFzjV2pRnUB57HvgNBV0fFffjLDRT+Bc2uY V5LdqRMOKmyWV1JyFUpqMPJTIUNWbpwCwHrMYA6glmYJ1JzLcBITEXclzY1YZuRrJ+AGze sol/wYhOJlo/13MIeDzPP29dqWzZIy4= X-MC-Unique: rEarg_nDMfG2T6YlCS6yKg-1 From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [PATCH v4 3/6] block-copy: improve comments of BlockCopyTask and BlockCopyState types and functions Date: Mon, 14 Jun 2021 09:33:47 +0200 Message-Id: <20210614073350.17048-4-eesposit@redhat.com> In-Reply-To: <20210614073350.17048-1-eesposit@redhat.com> References: <20210614073350.17048-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eesposit@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -29 X-Spam_score: -3.0 X-Spam_bar: --- X-Spam_report: (-3.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.199, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Emanuele Giuseppe Esposito , Vladimir Sementsov-Ogievskiy , qemu-devel@nongnu.org, Max Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) As done in BlockCopyCallState, categorize BlockCopyTask and BlockCopyState in IN, State and OUT fields. This is just to understand which field has to be protected with a lock. .sleep_state is handled in the series "coroutine: new sleep/wake API" and thus here left as TODO. Signed-off-by: Emanuele Giuseppe Esposito --- block/block-copy.c | 49 +++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index 3f26be8ddc..5ff7764e87 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -52,29 +52,35 @@ typedef struct BlockCopyCallState { /* Coroutine where async block-copy is running */ Coroutine *co; =20 - /* To reference all call states from BlockCopyState */ - QLIST_ENTRY(BlockCopyCallState) list; - /* State */ - int ret; bool finished; - QemuCoSleep sleep; - bool cancelled; + QemuCoSleep sleep; /* TODO: protect API with a lock */ + + /* To reference all call states from BlockCopyState */ + QLIST_ENTRY(BlockCopyCallState) list; =20 /* OUT parameters */ + bool cancelled; bool error_is_read; + int ret; } BlockCopyCallState; =20 typedef struct BlockCopyTask { AioTask task; =20 + /* + * IN parameters. Initialized in block_copy_task_create() + * and never changed. + */ BlockCopyState *s; BlockCopyCallState *call_state; int64_t offset; - int64_t bytes; BlockCopyMethod method; - QLIST_ENTRY(BlockCopyTask) list; + + /* State */ CoQueue wait_queue; /* coroutines blocked on this task */ + int64_t bytes; + QLIST_ENTRY(BlockCopyTask) list; } BlockCopyTask; =20 static int64_t task_end(BlockCopyTask *task) @@ -90,15 +96,25 @@ typedef struct BlockCopyState { */ BdrvChild *source; BdrvChild *target; - BdrvDirtyBitmap *copy_bitmap; + + /* State */ int64_t in_flight_bytes; - int64_t cluster_size; BlockCopyMethod method; - int64_t max_transfer; - uint64_t len; QLIST_HEAD(, BlockCopyTask) tasks; /* All tasks from all block-copy ca= lls */ QLIST_HEAD(, BlockCopyCallState) calls; + /* State fields that use a thread-safe API */ + BdrvDirtyBitmap *copy_bitmap; + ProgressMeter *progress; + SharedResource *mem; + RateLimit rate_limit; =20 + /* + * IN parameters. Initialized in block_copy_state_new() + * and never changed. + */ + int64_t cluster_size; + int64_t max_transfer; + uint64_t len; BdrvRequestFlags write_flags; =20 /* @@ -114,14 +130,11 @@ typedef struct BlockCopyState { * In this case, block_copy() will query the source=E2=80=99s allocati= on status, * skip unallocated regions, clear them in the copy_bitmap, and invoke * block_copy_reset_unallocated() every time it does. + * + * This field is set in backup_run() before coroutines are run, + * therefore is an IN. */ bool skip_unallocated; - - ProgressMeter *progress; - - SharedResource *mem; - - RateLimit rate_limit; } BlockCopyState; =20 static BlockCopyTask *find_conflicting_task(BlockCopyState *s, --=20 2.31.1 From nobody Sun Feb 8 13:10:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1623656231739873.0119877249238; Mon, 14 Jun 2021 00:37:11 -0700 (PDT) Received: from localhost ([::1]:41774 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lsh9i-0002Su-OV for importer@patchew.org; Mon, 14 Jun 2021 03:37:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35208) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6t-0005aT-UV for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:27565) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6p-00052u-UM for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:15 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-529-vs7Xg0o7Nryecva-n2_xcQ-1; Mon, 14 Jun 2021 03:34:09 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A2BA91850600; Mon, 14 Jun 2021 07:34:08 +0000 (UTC) Received: from localhost.localdomain (ovpn-113-49.ams2.redhat.com [10.36.113.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id 903335D6A8; Mon, 14 Jun 2021 07:34:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623656051; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bIie6F9dWto4e5Jw17Q4JRM5sd51ihjSQQl1VCmyr6k=; b=XfSZf7NZveGOdlCA1mvnOOextD1O1PmKUV4VWCSNNjAc7iphjfsaNEiNYDFHSzkJb0XqY0 ayhjNmY9oX3hSKOmfZxkxuLtlAS6Z82qiMBtjl1A9esqkD7Bkj5R2FUlxwLbQ+rivQEpwi X4Jb7tcQX2bJxmxEDPG6S9O5vnzQFrw= X-MC-Unique: vs7Xg0o7Nryecva-n2_xcQ-1 From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [PATCH v4 4/6] block-copy: move progress_set_remaining in block_copy_task_end Date: Mon, 14 Jun 2021 09:33:48 +0200 Message-Id: <20210614073350.17048-5-eesposit@redhat.com> In-Reply-To: <20210614073350.17048-1-eesposit@redhat.com> References: <20210614073350.17048-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eesposit@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -29 X-Spam_score: -3.0 X-Spam_bar: --- X-Spam_report: (-3.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.199, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Emanuele Giuseppe Esposito , Vladimir Sementsov-Ogievskiy , qemu-devel@nongnu.org, Max Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Moving this function in task_end ensures to update the progress anyways, even if there is an error. It also helps in next patch, allowing task_end to have only one critical section. Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Emanuele Giuseppe Esposito --- block/block-copy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index 5ff7764e87..afa2f484f0 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -261,6 +261,9 @@ static void coroutine_fn block_copy_task_end(BlockCopyT= ask *task, int ret) bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->by= tes); } QLIST_REMOVE(task, list); + progress_set_remaining(task->s->progress, + bdrv_get_dirty_count(task->s->copy_bitmap) + + task->s->in_flight_bytes); qemu_co_queue_restart_all(&task->wait_queue); } =20 @@ -651,9 +654,6 @@ block_copy_dirty_clusters(BlockCopyCallState *call_stat= e) } if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) { block_copy_task_end(task, 0); - progress_set_remaining(s->progress, - bdrv_get_dirty_count(s->copy_bitmap) + - s->in_flight_bytes); trace_block_copy_skip_range(s, task->offset, task->bytes); offset =3D task_end(task); bytes =3D end - offset; --=20 2.31.1 From nobody Sun Feb 8 13:10:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1623656340975864.0005614972971; Mon, 14 Jun 2021 00:39:00 -0700 (PDT) Received: from localhost ([::1]:47104 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lshBT-000629-UP for importer@patchew.org; Mon, 14 Jun 2021 03:38:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35228) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6w-0005jP-HZ for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:55981) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh6u-00056O-Hb for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:18 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-381-uIphKUlvMK6ffkpgQBzDFw-1; Mon, 14 Jun 2021 03:34:12 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 86B07801ADF; Mon, 14 Jun 2021 07:34:11 +0000 (UTC) Received: from localhost.localdomain (ovpn-113-49.ams2.redhat.com [10.36.113.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id 013E85D6A8; Mon, 14 Jun 2021 07:34:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623656056; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RmubNJaaWOZmDxPXbzCNnNArMjoF1vbOQWWhxx6eZEI=; b=bU1mLFXlpH/LxGtCEASUp96gpq9CN1Huf6qD7RBZyy4aixNV4TZry3RlkN/tByR4BO2JPc j9HD8qXVTA0J0HzDYogUzBPsYSizSOZ5lwupUAu0rIP0d7aJ4qvPkCUmBPBHWukT4/0Xe3 0/CHOmPnP41Zv7XmYxRLJNkbkJsUaV8= X-MC-Unique: uIphKUlvMK6ffkpgQBzDFw-1 From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [PATCH v4 5/6] block-copy: add a CoMutex Date: Mon, 14 Jun 2021 09:33:49 +0200 Message-Id: <20210614073350.17048-6-eesposit@redhat.com> In-Reply-To: <20210614073350.17048-1-eesposit@redhat.com> References: <20210614073350.17048-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eesposit@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -29 X-Spam_score: -3.0 X-Spam_bar: --- X-Spam_report: (-3.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.199, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Emanuele Giuseppe Esposito , Vladimir Sementsov-Ogievskiy , qemu-devel@nongnu.org, Max Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Add a CoMutex to protect concurrent access of block-copy data structures. This mutex also protects .copy_bitmap, because its thread-safe API does not prevent it from assigning two tasks to the same bitmap region. .finished, .cancelled and reads to .ret and .error_is_read will be protected in the following patch, because are used also outside coroutines. Also set block_copy_task_create as coroutine_fn because: 1) it is static and only invoked by coroutine functions 2) this patch introduces and uses a CoMutex lock there Signed-off-by: Emanuele Giuseppe Esposito --- block/block-copy.c | 79 +++++++++++++++++++++++++++++--------- include/block/block-copy.h | 2 + 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index afa2f484f0..6416929abd 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -61,6 +61,7 @@ typedef struct BlockCopyCallState { =20 /* OUT parameters */ bool cancelled; + /* Fields protected by lock in BlockCopyState */ bool error_is_read; int ret; } BlockCopyCallState; @@ -77,8 +78,12 @@ typedef struct BlockCopyTask { int64_t offset; BlockCopyMethod method; =20 - /* State */ + /* State. Protected by lock in BlockCopyState */ CoQueue wait_queue; /* coroutines blocked on this task */ + /* + * Only protect the case of parallel read while updating @bytes + * value in block_copy_task_shrink(). + */ int64_t bytes; QLIST_ENTRY(BlockCopyTask) list; } BlockCopyTask; @@ -97,7 +102,8 @@ typedef struct BlockCopyState { BdrvChild *source; BdrvChild *target; =20 - /* State */ + /* State. Protected by lock */ + CoMutex lock; int64_t in_flight_bytes; BlockCopyMethod method; QLIST_HEAD(, BlockCopyTask) tasks; /* All tasks from all block-copy ca= lls */ @@ -137,6 +143,7 @@ typedef struct BlockCopyState { bool skip_unallocated; } BlockCopyState; =20 +/* Called with lock held */ static BlockCopyTask *find_conflicting_task(BlockCopyState *s, int64_t offset, int64_t bytes) { @@ -154,6 +161,8 @@ static BlockCopyTask *find_conflicting_task(BlockCopySt= ate *s, /* * If there are no intersecting tasks return false. Otherwise, wait for the * first found intersecting tasks to finish and return true. + * + * Called with lock held. */ static bool coroutine_fn block_copy_wait_one(BlockCopyState *s, int64_t of= fset, int64_t bytes) @@ -164,7 +173,7 @@ static bool coroutine_fn block_copy_wait_one(BlockCopyS= tate *s, int64_t offset, return false; } =20 - qemu_co_queue_wait(&task->wait_queue, NULL); + qemu_co_queue_wait(&task->wait_queue, &s->lock); =20 return true; } @@ -191,14 +200,15 @@ static int64_t block_copy_chunk_size(BlockCopyState *= s) * Search for the first dirty area in offset/bytes range and create task at * the beginning of it. */ -static BlockCopyTask *block_copy_task_create(BlockCopyState *s, - BlockCopyCallState *call_stat= e, - int64_t offset, int64_t bytes) +static coroutine_fn BlockCopyTask *block_copy_task_create(BlockCopyState *= s, + BlockCopyCallState *call_s= tate, + int64_t offset, int64_t by= tes) { BlockCopyTask *task; - int64_t max_chunk =3D block_copy_chunk_size(s); + int64_t max_chunk; =20 - max_chunk =3D MIN_NON_ZERO(max_chunk, call_state->max_chunk); + QEMU_LOCK_GUARD(&s->lock); + max_chunk =3D MIN_NON_ZERO(block_copy_chunk_size(s), call_state->max_c= hunk); if (!bdrv_dirty_bitmap_next_dirty_area(s->copy_bitmap, offset, offset + bytes, max_chunk, &offset, &bytes)) @@ -240,6 +250,7 @@ static BlockCopyTask *block_copy_task_create(BlockCopyS= tate *s, static void coroutine_fn block_copy_task_shrink(BlockCopyTask *task, int64_t new_bytes) { + QEMU_LOCK_GUARD(&task->s->lock); if (new_bytes =3D=3D task->bytes) { return; } @@ -256,6 +267,7 @@ static void coroutine_fn block_copy_task_shrink(BlockCo= pyTask *task, =20 static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret) { + QEMU_LOCK_GUARD(&task->s->lock); task->s->in_flight_bytes -=3D task->bytes; if (ret < 0) { bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->by= tes); @@ -334,12 +346,14 @@ BlockCopyState *block_copy_state_new(BdrvChild *sourc= e, BdrvChild *target, } =20 ratelimit_init(&s->rate_limit); + qemu_co_mutex_init(&s->lock); QLIST_INIT(&s->tasks); QLIST_INIT(&s->calls); =20 return s; } =20 +/* Only set before running the job, so it is thread safe to call. */ void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm) { s->progress =3D pm; @@ -480,16 +494,20 @@ static coroutine_fn int block_copy_task_entry(AioTask= *task) int ret; =20 ret =3D block_copy_do_copy(s, t->offset, t->bytes, &method, &error_is_= read); - if (s->method =3D=3D t->method) { - s->method =3D method; - } - if (ret < 0) { - if (!t->call_state->ret) { - t->call_state->ret =3D ret; - t->call_state->error_is_read =3D error_is_read; + + WITH_QEMU_LOCK_GUARD(&s->lock) { + if (s->method =3D=3D t->method) { + s->method =3D method; + } + + if (ret < 0) { + if (!t->call_state->ret) { + t->call_state->ret =3D ret; + t->call_state->error_is_read =3D error_is_read; + } + } else { + progress_work_done(s->progress, t->bytes); } - } else { - progress_work_done(s->progress, t->bytes); } co_put_to_shres(s->mem, t->bytes); block_copy_task_end(t, ret); @@ -591,10 +609,12 @@ int64_t block_copy_reset_unallocated(BlockCopyState *= s, bytes =3D clusters * s->cluster_size; =20 if (!ret) { + qemu_co_mutex_lock(&s->lock); bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes); progress_set_remaining(s->progress, bdrv_get_dirty_count(s->copy_bitmap) + s->in_flight_bytes); + qemu_co_mutex_unlock(&s->lock); } =20 *count =3D bytes; @@ -734,14 +754,33 @@ static int coroutine_fn block_copy_common(BlockCopyCa= llState *call_state) int ret; BlockCopyState *s =3D call_state->s; =20 + qemu_co_mutex_lock(&s->lock); QLIST_INSERT_HEAD(&s->calls, call_state, list); + qemu_co_mutex_unlock(&s->lock); =20 do { ret =3D block_copy_dirty_clusters(call_state); =20 if (ret =3D=3D 0 && !call_state->cancelled) { - ret =3D block_copy_wait_one(s, call_state->offset, - call_state->bytes); + WITH_QEMU_LOCK_GUARD(&s->lock) { + /* + * Check that there is no task we still need to + * wait to complete + */ + ret =3D block_copy_wait_one(s, call_state->offset, + call_state->bytes); + if (ret =3D=3D 0) { + /* + * No pending tasks, but check again the bitmap in this + * same critical section, since a task might have fail= ed + * between this and the critical section in + * block_copy_dirty_clusters(). + */ + ret =3D bdrv_dirty_bitmap_next_dirty(s->copy_bitmap, + call_state->offset, + call_state->bytes) = > 0; + } + } } =20 /* @@ -761,7 +800,9 @@ static int coroutine_fn block_copy_common(BlockCopyCall= State *call_state) call_state->cb(call_state->cb_opaque); } =20 + qemu_co_mutex_lock(&s->lock); QLIST_REMOVE(call_state, list); + qemu_co_mutex_unlock(&s->lock); =20 return ret; } diff --git a/include/block/block-copy.h b/include/block/block-copy.h index 338f2ea7fd..bf8f0c679f 100644 --- a/include/block/block-copy.h +++ b/include/block/block-copy.h @@ -18,6 +18,8 @@ #include "block/block.h" #include "qemu/co-shared-resource.h" =20 +/* All APIs are thread-safe*/ + typedef void (*BlockCopyAsyncCallbackFunc)(void *opaque); typedef struct BlockCopyState BlockCopyState; typedef struct BlockCopyCallState BlockCopyCallState; --=20 2.31.1 From nobody Sun Feb 8 13:10:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1623656416650365.2766739272786; Mon, 14 Jun 2021 00:40:16 -0700 (PDT) Received: from localhost ([::1]:49834 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lshCh-0007ra-CJ for importer@patchew.org; Mon, 14 Jun 2021 03:40:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35258) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh72-00066s-M6 for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:26 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:48265) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lsh70-0005Ba-TZ for qemu-devel@nongnu.org; Mon, 14 Jun 2021 03:34:24 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-346-Woc9fdl4PnWrNZxHSpf0Tw-1; Mon, 14 Jun 2021 03:34:21 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 25126100C661; Mon, 14 Jun 2021 07:34:20 +0000 (UTC) Received: from localhost.localdomain (ovpn-113-49.ams2.redhat.com [10.36.113.49]) by smtp.corp.redhat.com (Postfix) with ESMTP id DE6085D6A8; Mon, 14 Jun 2021 07:34:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1623656062; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XL9LfIfxRN2XjFCD+OVGMrlQ/snVijAp3KeI/NwqtF4=; b=LJ8b0mZ5eD8HeSHezZ9iWYu4Y2trRsGswLIY96lFJ9Ky+JYzFL9KYgYIXrMVZaYkgbHI9J N2sOU79kb9oV2X0eY7Cb0yDFK41/G+5gUbCuj+mOB3HDk6JwpSZmC7RLbGe/hVJdhmP/m3 UjlFCnTTI6qIN8ZZwVNaJz0fPVMBmaQ= X-MC-Unique: Woc9fdl4PnWrNZxHSpf0Tw-1 From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [PATCH v4 6/6] block-copy: atomic .cancelled and .finished fields in BlockCopyCallState Date: Mon, 14 Jun 2021 09:33:50 +0200 Message-Id: <20210614073350.17048-7-eesposit@redhat.com> In-Reply-To: <20210614073350.17048-1-eesposit@redhat.com> References: <20210614073350.17048-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=eesposit@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -29 X-Spam_score: -3.0 X-Spam_bar: --- X-Spam_report: (-3.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.199, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Emanuele Giuseppe Esposito , Vladimir Sementsov-Ogievskiy , qemu-devel@nongnu.org, Max Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" By adding acquire/release pairs, we ensure that .ret and .error_is_read fields are written by block_copy_dirty_clusters before .finished is true. The atomic here are necessary because the fields are concurrently modified also outside coroutines. Signed-off-by: Emanuele Giuseppe Esposito --- block/block-copy.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/block/block-copy.c b/block/block-copy.c index 6416929abd..5348e1f61b 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -53,14 +53,14 @@ typedef struct BlockCopyCallState { Coroutine *co; =20 /* State */ - bool finished; + bool finished; /* atomic */ QemuCoSleep sleep; /* TODO: protect API with a lock */ =20 /* To reference all call states from BlockCopyState */ QLIST_ENTRY(BlockCopyCallState) list; =20 /* OUT parameters */ - bool cancelled; + bool cancelled; /* atomic */ /* Fields protected by lock in BlockCopyState */ bool error_is_read; int ret; @@ -650,7 +650,8 @@ block_copy_dirty_clusters(BlockCopyCallState *call_stat= e) assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); assert(QEMU_IS_ALIGNED(bytes, s->cluster_size)); =20 - while (bytes && aio_task_pool_status(aio) =3D=3D 0 && !call_state->can= celled) { + while (bytes && aio_task_pool_status(aio) =3D=3D 0 && + !qatomic_read(&call_state->cancelled)) { BlockCopyTask *task; int64_t status_bytes; =20 @@ -761,7 +762,7 @@ static int coroutine_fn block_copy_common(BlockCopyCall= State *call_state) do { ret =3D block_copy_dirty_clusters(call_state); =20 - if (ret =3D=3D 0 && !call_state->cancelled) { + if (ret =3D=3D 0 && !qatomic_read(&call_state->cancelled)) { WITH_QEMU_LOCK_GUARD(&s->lock) { /* * Check that there is no task we still need to @@ -792,9 +793,9 @@ static int coroutine_fn block_copy_common(BlockCopyCall= State *call_state) * 2. We have waited for some intersecting block-copy request * It may have failed and produced new dirty bits. */ - } while (ret > 0 && !call_state->cancelled); + } while (ret > 0 && !qatomic_read(&call_state->cancelled)); =20 - call_state->finished =3D true; + qatomic_store_release(&call_state->finished, true); =20 if (call_state->cb) { call_state->cb(call_state->cb_opaque); @@ -857,35 +858,37 @@ void block_copy_call_free(BlockCopyCallState *call_st= ate) return; } =20 - assert(call_state->finished); + assert(qatomic_load_acquire(&call_state->finished)); g_free(call_state); } =20 bool block_copy_call_finished(BlockCopyCallState *call_state) { - return call_state->finished; + return qatomic_load_acquire(&call_state->finished); } =20 bool block_copy_call_succeeded(BlockCopyCallState *call_state) { - return call_state->finished && !call_state->cancelled && - call_state->ret =3D=3D 0; + return qatomic_load_acquire(&call_state->finished) && + !qatomic_read(&call_state->cancelled) && + call_state->ret =3D=3D 0; } =20 bool block_copy_call_failed(BlockCopyCallState *call_state) { - return call_state->finished && !call_state->cancelled && - call_state->ret < 0; + return qatomic_load_acquire(&call_state->finished) && + !qatomic_read(&call_state->cancelled) && + call_state->ret < 0; } =20 bool block_copy_call_cancelled(BlockCopyCallState *call_state) { - return call_state->cancelled; + return qatomic_read(&call_state->cancelled); } =20 int block_copy_call_status(BlockCopyCallState *call_state, bool *error_is_= read) { - assert(call_state->finished); + assert(qatomic_load_acquire(&call_state->finished)); if (error_is_read) { *error_is_read =3D call_state->error_is_read; } @@ -894,7 +897,7 @@ int block_copy_call_status(BlockCopyCallState *call_sta= te, bool *error_is_read) =20 void block_copy_call_cancel(BlockCopyCallState *call_state) { - call_state->cancelled =3D true; + qatomic_set(&call_state->cancelled, true); block_copy_kick(call_state); } =20 --=20 2.31.1