From patchwork Fri Sep 11 14:09:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Garcia X-Patchwork-Id: 1362466 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=igalia.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.a=rsa-sha256 header.s=20170329 header.b=AsPPcU4m; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BnyMm5pc8z9sSs for ; Sat, 12 Sep 2020 00:10:44 +1000 (AEST) Received: from localhost ([::1]:51184 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kGjlC-0004Ou-NY for incoming@patchwork.ozlabs.org; Fri, 11 Sep 2020 10:10:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45376) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kGjka-0004OH-1V; Fri, 11 Sep 2020 10:10:04 -0400 Received: from fanzine.igalia.com ([178.60.130.6]:50976) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kGjkW-0000h9-Kw; Fri, 11 Sep 2020 10:10:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=Uj8oGFGFid1keo97GpxzEqjju8VM0l2+7NhMncE/GrM=; b=AsPPcU4mGQMmt3hBprEZemf94oHY08xaCIuTf/b5CNxRyjiR5sX3OfYG4Pyo6swmfLxy6LaqUKv/OWrYzsd39fW9k/W64L70DoNOX92KBAJ7ZFCp1yS3k2tVKdldtf/LBxuNK4ZKidYpfEQJxnp3TMUuu0muiO0PuDubpn33yB7+qXYjXBBZuiGOLBYSYcs5YRMj71lOf/TIIzAJbqcPjpTM135rMoWZJdDXi7LL8zubvdAGGwwXkD9n7fg7karsvDnL4IcdFsF1TKehblvApe7tdXK//BgrNGxMauIONqU9Xt67uldPXCMmK2HpW3QDGHdCs1ODFGa8YES2Y8K3Hw==; Received: from [81.0.39.67] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1kGjkR-0004ol-Su; Fri, 11 Sep 2020 16:09:55 +0200 Received: from berto by perseus.local with local (Exim 4.92) (envelope-from ) id 1kGjkF-0000zu-2E; Fri, 11 Sep 2020 16:09:43 +0200 From: Alberto Garcia To: qemu-devel@nongnu.org Subject: [PATCH 1/2] qcow2: Make preallocate_co() resize the image to the correct size Date: Fri, 11 Sep 2020 16:09:41 +0200 Message-Id: X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=178.60.130.6; envelope-from=berto@igalia.com; helo=fanzine.igalia.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/11 10:09:56 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This function preallocates metadata structures and then extends the image to its new size, but that new size calculation is wrong because it doesn't take into account that the host_offset variable is always cluster-aligned. This problem can be reproduced with preallocation=metadata when the original size is not cluster-aligned but the new size is. In this case the final image size will be shorter than expected. qemu-img create -f qcow2 img.qcow2 31k qemu-img resize --preallocation=metadata img.qcow2 128k Signed-off-by: Alberto Garcia Reviewed-by: Max Reitz --- block/qcow2.c | 1 + tests/qemu-iotests/125 | 40 +++++++++++++++++++++----------------- tests/qemu-iotests/125.out | 28 ++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 77c43ce178..1cb5daf39a 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3135,6 +3135,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, error_setg_errno(errp, -ret, "Allocating clusters failed"); goto out; } + host_offset += offset_into_cluster(s, offset); for (m = meta; m != NULL; m = m->next) { m->prealloc = true; diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125 index 7cb1c19730..1f35598b2b 100755 --- a/tests/qemu-iotests/125 +++ b/tests/qemu-iotests/125 @@ -168,24 +168,28 @@ done $QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create $QEMU_IO -c 'write -q -P 1 0 128k' -f raw "$TEST_IMG.base" for orig_size in 31k 33k; do - echo "--- Resizing image from $orig_size to 96k ---" - _make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size" - $QEMU_IMG resize -f "$IMGFMT" --preallocation=full "$TEST_IMG" 96k - # The first part of the image should contain data from the backing file - $QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG" - # The resized part of the image should contain zeroes - $QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG" - # If the image does not have an external data file we can also verify its - # actual size. The resized image should have 7 clusters: - # header, L1 table, L2 table, refcount table, refcount block, 2 data clusters - if ! _get_data_file "$TEST_IMG" > /dev/null; then - expected_file_length=$((65536 * 7)) - file_length=$(stat -c '%s' "$TEST_IMG_FILE") - if [ "$file_length" != "$expected_file_length" ]; then - echo "ERROR: file length $file_length (expected $expected_file_length)" - fi - fi - echo + for dst_size in 96k 128k; do + for prealloc in metadata full; do + echo "--- Resizing image from $orig_size to $dst_size (preallocation=$prealloc) ---" + _make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size" + $QEMU_IMG resize -f "$IMGFMT" --preallocation="$prealloc" "$TEST_IMG" "$dst_size" + # The first part of the image should contain data from the backing file + $QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG" + # The resized part of the image should contain zeroes + $QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG" + # If the image does not have an external data file we can also verify its + # actual size. The resized image should have 7 clusters: + # header, L1 table, L2 table, refcount table, refcount block, 2 data clusters + if ! _get_data_file "$TEST_IMG" > /dev/null; then + expected_file_length=$((65536 * 7)) + file_length=$(stat -c '%s' "$TEST_IMG_FILE") + if [ "$file_length" != "$expected_file_length" ]; then + echo "ERROR: file length $file_length (expected $expected_file_length)" + fi + fi + echo + done + done done # success, all done diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out index 7f76f7af20..63a6e9e8a9 100644 --- a/tests/qemu-iotests/125.out +++ b/tests/qemu-iotests/125.out @@ -768,11 +768,35 @@ wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=131072 ---- Resizing image from 31k to 96k --- +--- Resizing image from 31k to 96k (preallocation=metadata) --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw Image resized. ---- Resizing image from 33k to 96k --- +--- Resizing image from 31k to 96k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 31k to 128k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 31k to 128k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 96k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 96k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 128k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 128k (preallocation=full) --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw Image resized. From patchwork Fri Sep 11 14:09:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Garcia X-Patchwork-Id: 1362468 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=igalia.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.a=rsa-sha256 header.s=20170329 header.b=cjMHGRlH; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BnyPQ5FByz9sSs for ; Sat, 12 Sep 2020 00:12:10 +1000 (AEST) Received: from localhost ([::1]:55846 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kGjmZ-0006X2-Hc for incoming@patchwork.ozlabs.org; Fri, 11 Sep 2020 10:12:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45386) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kGjka-0004OR-Lj; Fri, 11 Sep 2020 10:10:04 -0400 Received: from fanzine.igalia.com ([178.60.130.6]:50977) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kGjkW-0000hA-Bo; Fri, 11 Sep 2020 10:10:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=8tUH1cre38QiqztWRmULDkd1dxIU2P18eyDpmVz0nYc=; b=cjMHGRlH3VzLqU9oy9/rnF2nTPQubbKJHJI8xlUmDeJqTZwWf4ZL1nNUYJPiHZW1VNDXyNVOitVaeqt6qgT7bmjcU23v8eaHeABxPmn88SSB/jJKka/FQw16deEEv2M2cj3+//DYb0wii2+tWOrLiyyxa6/ytwqmYYsIiwyrUUaUkxz0v9LqfuC1ba3ads4TuIVs9LhcroFCoROcjpliBZ8D/teJE/elJbVZQu4F0CiFojArRXwWd2EAI6d3BbkkR890u37Bzb9lJukbBWtOtAnsktcIhm1ZXETVIL9fbgqCV/7GO6ahc8oaruBhHiafhUacPwWyV5aYY7o77XpelQ==; Received: from [81.0.39.67] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1kGjkS-0004om-00; Fri, 11 Sep 2020 16:09:56 +0200 Received: from berto by perseus.local with local (Exim 4.92) (envelope-from ) id 1kGjkF-0000zw-3D; Fri, 11 Sep 2020 16:09:43 +0200 From: Alberto Garcia To: qemu-devel@nongnu.org Subject: [PATCH 2/2] qcow2: Convert qcow2_alloc_cluster_offset() into qcow2_alloc_host_offset() Date: Fri, 11 Sep 2020 16:09:42 +0200 Message-Id: <9bfef50ec9200d752413be4fc2aeb22a28378817.1599833007.git.berto@igalia.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=178.60.130.6; envelope-from=berto@igalia.com; helo=fanzine.igalia.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/09/11 10:09:56 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, 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 , Alberto Garcia , qemu-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" qcow2_alloc_cluster_offset() takes an (unaligned) guest offset and returns the (aligned) offset of the corresponding cluster in the qcow2 image. In practice none of the callers need to know where the cluster starts so this patch makes the function calculate and return the final host offset directly. The function is also renamed accordingly. See 388e581615 for a similar change to qcow2_get_cluster_offset(). Signed-off-by: Alberto Garcia Reviewed-by: Max Reitz --- block/qcow2.h | 6 +++--- block/qcow2-cluster.c | 14 ++++++++++---- block/qcow2.c | 36 +++++++++++++----------------------- 3 files changed, 26 insertions(+), 30 deletions(-) diff --git a/block/qcow2.h b/block/qcow2.h index b73a4cf1f8..b71e444fca 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -901,9 +901,9 @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset, unsigned int *bytes, uint64_t *host_offset, QCow2SubclusterType *subcluster_type); -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *host_offset, - QCowL2Meta **m); +int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, uint64_t *host_offset, + QCowL2Meta **m); int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, int compressed_size, diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 1a67b2d928..9acc6ce4ae 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1719,6 +1719,10 @@ out: * clusters (or subclusters) if necessary. The result can span a * combination of allocated and previously unallocated clusters. * + * Note that offset may not be cluster aligned. In this case, the returned + * *host_offset points to exact byte referenced by offset and therefore + * isn't cluster aligned as well. + * * On return, @host_offset is set to the beginning of the requested * area. This area is guaranteed to be contiguous on the qcow2 file * but it can be smaller than initially requested. In this case @bytes @@ -1736,9 +1740,9 @@ out: * * Return 0 on success and -errno in error cases */ -int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *host_offset, - QCowL2Meta **m) +int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, uint64_t *host_offset, + QCowL2Meta **m) { BDRVQcow2State *s = bs->opaque; uint64_t start, remaining; @@ -1759,7 +1763,7 @@ again: while (true) { if (*host_offset == INV_OFFSET && cluster_offset != INV_OFFSET) { - *host_offset = start_of_cluster(s, cluster_offset); + *host_offset = cluster_offset; } assert(remaining >= cur_bytes); @@ -1842,6 +1846,8 @@ again: *bytes -= remaining; assert(*bytes > 0); assert(*host_offset != INV_OFFSET); + assert(offset_into_cluster(s, *host_offset) == + offset_into_cluster(s, offset)); return 0; } diff --git a/block/qcow2.c b/block/qcow2.c index 1cb5daf39a..b05512718c 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2559,7 +2559,7 @@ static coroutine_fn int qcow2_co_pwritev_part( int offset_in_cluster; int ret; unsigned int cur_bytes; /* number of sectors in current iteration */ - uint64_t cluster_offset; + uint64_t host_offset; QCowL2Meta *l2meta = NULL; AioTaskPool *aio = NULL; @@ -2580,16 +2580,13 @@ static coroutine_fn int qcow2_co_pwritev_part( qemu_co_mutex_lock(&s->lock); - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, - &cluster_offset, &l2meta); + ret = qcow2_alloc_host_offset(bs, offset, &cur_bytes, + &host_offset, &l2meta); if (ret < 0) { goto out_locked; } - assert(offset_into_cluster(s, cluster_offset) == 0); - - ret = qcow2_pre_write_overlap_check(bs, 0, - cluster_offset + offset_in_cluster, + ret = qcow2_pre_write_overlap_check(bs, 0, host_offset, cur_bytes, true); if (ret < 0) { goto out_locked; @@ -2601,7 +2598,7 @@ static coroutine_fn int qcow2_co_pwritev_part( aio = aio_task_pool_new(QCOW2_MAX_WORKERS); } ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0, - cluster_offset + offset_in_cluster, offset, + host_offset, offset, cur_bytes, qiov, qiov_offset, l2meta); l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */ if (ret < 0) { @@ -3129,13 +3126,12 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset, while (bytes) { cur_bytes = MIN(bytes, QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size)); - ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes, - &host_offset, &meta); + ret = qcow2_alloc_host_offset(bs, offset, &cur_bytes, + &host_offset, &meta); if (ret < 0) { error_setg_errno(errp, -ret, "Allocating clusters failed"); goto out; } - host_offset += offset_into_cluster(s, offset); for (m = meta; m != NULL; m = m->next) { m->prealloc = true; @@ -4043,10 +4039,9 @@ qcow2_co_copy_range_to(BlockDriverState *bs, BdrvRequestFlags write_flags) { BDRVQcow2State *s = bs->opaque; - int offset_in_cluster; int ret; unsigned int cur_bytes; /* number of sectors in current iteration */ - uint64_t cluster_offset; + uint64_t host_offset; QCowL2Meta *l2meta = NULL; assert(!bs->encrypted); @@ -4057,31 +4052,26 @@ qcow2_co_copy_range_to(BlockDriverState *bs, l2meta = NULL; - offset_in_cluster = offset_into_cluster(s, dst_offset); cur_bytes = MIN(bytes, INT_MAX); /* TODO: * If src->bs == dst->bs, we could simply copy by incrementing * the refcnt, without copying user data. * Or if src->bs == dst->bs->backing->bs, we could copy by discarding. */ - ret = qcow2_alloc_cluster_offset(bs, dst_offset, &cur_bytes, - &cluster_offset, &l2meta); + ret = qcow2_alloc_host_offset(bs, dst_offset, &cur_bytes, + &host_offset, &l2meta); if (ret < 0) { goto fail; } - assert(offset_into_cluster(s, cluster_offset) == 0); - - ret = qcow2_pre_write_overlap_check(bs, 0, - cluster_offset + offset_in_cluster, cur_bytes, true); + ret = qcow2_pre_write_overlap_check(bs, 0, host_offset, cur_bytes, + true); if (ret < 0) { goto fail; } qemu_co_mutex_unlock(&s->lock); - ret = bdrv_co_copy_range_to(src, src_offset, - s->data_file, - cluster_offset + offset_in_cluster, + ret = bdrv_co_copy_range_to(src, src_offset, s->data_file, host_offset, cur_bytes, read_flags, write_flags); qemu_co_mutex_lock(&s->lock); if (ret < 0) {