From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542635; cv=none; d=zohomail.com; s=zohoarc; b=a24bxtFLHjx+iy1cHWJbhsn+/uMx1SNv2Cr89Lyj2mjXUVE9+PO1AW8LhtsEpN/CL7PQ9HKMoG0YQtIfkdMQbYSaqivxjoi/z+nOWDJU8eqT79ISE7Gciw0yS07Syp9bqCBkk4M6Zjd5UdeWt52ihKD3kg97okIZcw4nmWiSdlU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542635; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=2e3tJeOwzByqIpfXhBrJ9O/hfq/1Jkn7VZT9Y0CpDR0=; b=giN6GFjmkkEuiQ4MPbQCdS8lE/C4xjQ+hj4Ieh6y1mYzgqIICLyZ0FkR7Kry5fhpM91a8eEX6tjCl+ZLjQHuOY7XmbeufFGgdh44593vm0fNPNudQjgGiWmUj8WzfXtc2+lNh1egrYohdQ8j7ARAax/eqP2I4lIvzmfklvh4B3I= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 174554263501024.55527175063412; Thu, 24 Apr 2025 17:57:15 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87LV-0006ZJ-ET; Thu, 24 Apr 2025 20:55:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LS-0006UK-5M for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:10 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LO-0000hA-9x for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:09 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-456-utC2JY2PMCqdiIZzHatdlQ-1; Thu, 24 Apr 2025 20:55:01 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7C9FC18001CA; Fri, 25 Apr 2025 00:54:58 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8D7531800378; Fri, 25 Apr 2025 00:54:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542504; 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=2e3tJeOwzByqIpfXhBrJ9O/hfq/1Jkn7VZT9Y0CpDR0=; b=NhMvrc9OQMEivBkdugeXhBxredUe+GOyNmis2guZlED856Q4WWDtkKgBEW/LBuKX2sgZJt Pme2xYKW3CbDCV8zPQ02hiiCxCDw9kBEstFNlF3TI5TrRTIbLEZMj1B5uHUG+2mQuLZC0S MTsQYW2L57oXSAQv5TboxK2u0KwRgNE= X-MC-Unique: utC2JY2PMCqdiIZzHatdlQ-1 X-Mimecast-MFC-AGG-ID: utC2JY2PMCqdiIZzHatdlQ_1745542499 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Kevin Wolf , Hanna Reitz , John Snow , Fam Zheng , Ronnie Sahlberg , Paolo Bonzini , Peter Lieven , "Denis V. Lunev" , Alberto Garcia , Ilya Dryomov , Stefan Weil , integration@gluster.org (open list:GLUSTER) Subject: [PATCH v3 01/11] block: Expand block status mode from bool to flags Date: Thu, 24 Apr 2025 19:52:01 -0500 Message-ID: <20250425005439.2252467-14-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542638264019100 Content-Type: text/plain; charset="utf-8" This patch is purely mechanical, changing bool want_zero into an unsigned int for bitwise-or of flags. As of this patch, all implementations are unchanged (the old want_zero=3D=3Dtrue is now mode=3D=3DBDRV_WANT_PRECISE which is a superset of BDRV_WANT_ZERO); but the callers in io.c that used to pass want_zero=3D=3Dfalse are now prepared for future driver changes that can now distinguish bewteen BDRV_WANT_ZERO vs. BDRV_WANT_ALLOCATED. The next patch will actually change the file-posix driver along those lines, now that we have more-specific hints. As for the background why this patch is useful: right now, the file-posix driver recognizes that if allocation is being queried, the entire image can be reported as allocated (there is no backing file to refer to) - but this throws away information on whether the entire image reads as zero (trivially true if lseek(SEEK_HOLE) at offset 0 returns -ENXIO, a bit more complicated to prove if the raw file was created with 'qemu-img create' since we intentionally allocate a small chunk of all-zero data to help with alignment probing). Later patches will add a generic algorithm for seeing if an entire file reads as zeroes. Signed-off-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- block/coroutines.h | 4 +-- include/block/block-common.h | 11 +++++++ include/block/block_int-common.h | 27 +++++++++-------- include/block/block_int-io.h | 4 +-- block/io.c | 51 ++++++++++++++++---------------- block/blkdebug.c | 6 ++-- block/copy-before-write.c | 4 +-- block/file-posix.c | 4 +-- block/gluster.c | 4 +-- block/iscsi.c | 6 ++-- block/nbd.c | 4 +-- block/null.c | 6 ++-- block/parallels.c | 6 ++-- block/qcow.c | 2 +- block/qcow2.c | 6 ++-- block/qed.c | 6 ++-- block/quorum.c | 4 +-- block/raw-format.c | 4 +-- block/rbd.c | 6 ++-- block/snapshot-access.c | 4 +-- block/vdi.c | 4 +-- block/vmdk.c | 2 +- block/vpc.c | 2 +- block/vvfat.c | 6 ++-- tests/unit/test-block-iothread.c | 2 +- 25 files changed, 99 insertions(+), 86 deletions(-) diff --git a/block/coroutines.h b/block/coroutines.h index 79e5efbf752..892646bb7aa 100644 --- a/block/coroutines.h +++ b/block/coroutines.h @@ -47,7 +47,7 @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_common_block_status_above(BlockDriverState *bs, BlockDriverState *base, bool include_base, - bool want_zero, + unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, @@ -78,7 +78,7 @@ int co_wrapper_mixed_bdrv_rdlock bdrv_common_block_status_above(BlockDriverState *bs, BlockDriverState *base, bool include_base, - bool want_zero, + unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, diff --git a/include/block/block-common.h b/include/block/block-common.h index 0b831ef87b1..c8c626daeaa 100644 --- a/include/block/block-common.h +++ b/include/block/block-common.h @@ -333,6 +333,17 @@ typedef enum { #define BDRV_BLOCK_RECURSE 0x40 #define BDRV_BLOCK_COMPRESSED 0x80 +/* + * Block status hints: the bitwise-or of these flags emphasize what + * the caller hopes to learn, and some drivers may be able to give + * faster answers by doing less work when the hint permits. + */ +#define BDRV_WANT_ZERO BDRV_BLOCK_ZERO +#define BDRV_WANT_OFFSET_VALID BDRV_BLOCK_OFFSET_VALID +#define BDRV_WANT_ALLOCATED BDRV_BLOCK_ALLOCATED +#define BDRV_WANT_PRECISE (BDRV_WANT_ZERO | BDRV_WANT_OFFSET_VALID |= \ + BDRV_WANT_OFFSET_VALID) + typedef QTAILQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQu= eue; typedef struct BDRVReopenState { diff --git a/include/block/block_int-common.h b/include/block/block_int-com= mon.h index ebb4e56a503..a9c0daa2a4d 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -608,15 +608,16 @@ struct BlockDriver { * according to the current layer, and should only need to set * BDRV_BLOCK_DATA, BDRV_BLOCK_ZERO, BDRV_BLOCK_OFFSET_VALID, * and/or BDRV_BLOCK_RAW; if the current layer defers to a backing - * layer, the result should be 0 (and not BDRV_BLOCK_ZERO). See - * block.h for the overall meaning of the bits. As a hint, the - * flag want_zero is true if the caller cares more about precise - * mappings (favor accurate _OFFSET_VALID/_ZERO) or false for - * overall allocation (favor larger *pnum, perhaps by reporting - * _DATA instead of _ZERO). The block layer guarantees input - * clamped to bdrv_getlength() and aligned to request_alignment, - * as well as non-NULL pnum, map, and file; in turn, the driver - * must return an error or set pnum to an aligned non-zero value. + * layer, the result should be 0 (and not BDRV_BLOCK_ZERO). The + * caller will synthesize BDRV_BLOCK_ALLOCATED based on the + * non-zero results. See block.h for the overall meaning of the + * bits. As a hint, the flags in @mode may include a bitwise-or + * of BDRV_WANT_ALLOCATED, BDRV_WANT_OFFSET_VALID, or + * BDRV_WANT_ZERO based on what the caller is looking for in the + * results. The block layer guarantees input clamped to + * bdrv_getlength() and aligned to request_alignment, as well as + * non-NULL pnum, map, and file; in turn, the driver must return + * an error or set pnum to an aligned non-zero value. * * Note that @bytes is just a hint on how big of a region the * caller wants to inspect. It is not a limit on *pnum. @@ -628,8 +629,8 @@ struct BlockDriver { * to clamping *pnum for return to its caller. */ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_block_status)( - BlockDriverState *bs, - bool want_zero, int64_t offset, int64_t bytes, int64_t *pnum, + BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file); /* @@ -653,8 +654,8 @@ struct BlockDriver { QEMUIOVector *qiov, size_t qiov_offset); int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_snapshot_block_status)( - BlockDriverState *bs, bool want_zero, int64_t offset, int64_t byte= s, - int64_t *pnum, int64_t *map, BlockDriverState **file); + BlockDriverState *bs, unsigned int mode, int64_t offset, + int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **fil= e); int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_pdiscard_snapshot)( BlockDriverState *bs, int64_t offset, int64_t bytes); diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 4a7cf2b4fdc..4f94eb3c5a2 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -38,8 +38,8 @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset); int coroutine_fn GRAPH_RDLOCK bdrv_co_snapshot_block_status( - BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes, - int64_t *pnum, int64_t *map, BlockDriverState **file); + BlockDriverState *bs, unsigned int mode, int64_t offset, + int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file); int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard_snapshot(BlockDriverState *= bs, int64_t offset, int64_t bytes); diff --git a/block/io.c b/block/io.c index 1ba8d1aeea1..056af8198bc 100644 --- a/block/io.c +++ b/block/io.c @@ -2364,10 +2364,8 @@ int bdrv_flush_all(void) * Drivers not implementing the functionality are assumed to not support * backing files, hence all their sectors are reported as allocated. * - * If 'want_zero' is true, the caller is querying for mapping - * purposes, with a focus on valid BDRV_BLOCK_OFFSET_VALID, _DATA, and - * _ZERO where possible; otherwise, the result favors larger 'pnum', - * with a focus on accurate BDRV_BLOCK_ALLOCATED. + * 'mode' serves as a hint as to which results are favored; see the + * BDRV_WANT_* macros for details. * * If 'offset' is beyond the end of the disk image the return value is * BDRV_BLOCK_EOF and 'pnum' is set to 0. @@ -2387,7 +2385,7 @@ int bdrv_flush_all(void) * set to the host mapping and BDS corresponding to the guest offset. */ static int coroutine_fn GRAPH_RDLOCK -bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero, +bdrv_co_do_block_status(BlockDriverState *bs, unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **fi= le) { @@ -2476,7 +2474,7 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool wa= nt_zero, local_file =3D bs; local_map =3D aligned_offset; } else { - ret =3D bs->drv->bdrv_co_block_status(bs, want_zero, aligned_o= ffset, + ret =3D bs->drv->bdrv_co_block_status(bs, mode, aligned_offset, aligned_bytes, pnum, &loca= l_map, &local_file); @@ -2488,10 +2486,10 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool = want_zero, * the cache requires an RCU update, so double check here to a= void * such an update if possible. * - * Check want_zero, because we only want to update the cache w= hen we + * Check mode, because we only want to update the cache when we * have accurate information about what is zero and what is da= ta. */ - if (want_zero && + if (mode =3D=3D BDRV_WANT_PRECISE && ret =3D=3D (BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID) && QLIST_EMPTY(&bs->children)) { @@ -2548,7 +2546,7 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool wa= nt_zero, if (ret & BDRV_BLOCK_RAW) { assert(ret & BDRV_BLOCK_OFFSET_VALID && local_file); - ret =3D bdrv_co_do_block_status(local_file, want_zero, local_map, + ret =3D bdrv_co_do_block_status(local_file, mode, local_map, *pnum, pnum, &local_map, &local_file= ); goto out; } @@ -2560,7 +2558,7 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool wa= nt_zero, if (!cow_bs) { ret |=3D BDRV_BLOCK_ZERO; - } else if (want_zero) { + } else if (mode =3D=3D BDRV_WANT_PRECISE) { int64_t size2 =3D bdrv_co_getlength(cow_bs); if (size2 >=3D 0 && offset >=3D size2) { @@ -2569,14 +2567,14 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool = want_zero, } } - if (want_zero && ret & BDRV_BLOCK_RECURSE && + if (mode =3D=3D BDRV_WANT_PRECISE && ret & BDRV_BLOCK_RECURSE && local_file && local_file !=3D bs && (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) && (ret & BDRV_BLOCK_OFFSET_VALID)) { int64_t file_pnum; int ret2; - ret2 =3D bdrv_co_do_block_status(local_file, want_zero, local_map, + ret2 =3D bdrv_co_do_block_status(local_file, mode, local_map, *pnum, &file_pnum, NULL, NULL); if (ret2 >=3D 0) { /* Ignore errors. This is just providing extra information, it @@ -2627,7 +2625,7 @@ int coroutine_fn bdrv_co_common_block_status_above(BlockDriverState *bs, BlockDriverState *base, bool include_base, - bool want_zero, + unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, @@ -2654,7 +2652,7 @@ bdrv_co_common_block_status_above(BlockDriverState *b= s, return 0; } - ret =3D bdrv_co_do_block_status(bs, want_zero, offset, bytes, pnum, + ret =3D bdrv_co_do_block_status(bs, mode, offset, bytes, pnum, map, file); ++*depth; if (ret < 0 || *pnum =3D=3D 0 || ret & BDRV_BLOCK_ALLOCATED || bs =3D= =3D base) { @@ -2671,7 +2669,7 @@ bdrv_co_common_block_status_above(BlockDriverState *b= s, for (p =3D bdrv_filter_or_cow_bs(bs); include_base || p !=3D base; p =3D bdrv_filter_or_cow_bs(p)) { - ret =3D bdrv_co_do_block_status(p, want_zero, offset, bytes, pnum, + ret =3D bdrv_co_do_block_status(p, mode, offset, bytes, pnum, map, file); ++*depth; if (ret < 0) { @@ -2734,7 +2732,8 @@ int coroutine_fn bdrv_co_block_status_above(BlockDriv= erState *bs, BlockDriverState **file) { IO_CODE(); - return bdrv_co_common_block_status_above(bs, base, false, true, offset, + return bdrv_co_common_block_status_above(bs, base, false, + BDRV_WANT_PRECISE, offset, bytes, pnum, map, file, NULL); } @@ -2765,8 +2764,9 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverStat= e *bs, int64_t offset, return 1; } - ret =3D bdrv_co_common_block_status_above(bs, NULL, false, false, offs= et, - bytes, &pnum, NULL, NULL, NULL= ); + ret =3D bdrv_co_common_block_status_above(bs, NULL, false, BDRV_WANT_Z= ERO, + offset, bytes, &pnum, NULL, NU= LL, + NULL); if (ret < 0) { return ret; @@ -2782,9 +2782,9 @@ int coroutine_fn bdrv_co_is_allocated(BlockDriverStat= e *bs, int64_t offset, int64_t dummy; IO_CODE(); - ret =3D bdrv_co_common_block_status_above(bs, bs, true, false, offset, - bytes, pnum ? pnum : &dummy, N= ULL, - NULL, NULL); + ret =3D bdrv_co_common_block_status_above(bs, bs, true, BDRV_WANT_ALLO= CATED, + offset, bytes, pnum ? pnum : &= dummy, + NULL, NULL, NULL); if (ret < 0) { return ret; } @@ -2817,7 +2817,8 @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriv= erState *bs, int ret; IO_CODE(); - ret =3D bdrv_co_common_block_status_above(bs, base, include_base, fals= e, + ret =3D bdrv_co_common_block_status_above(bs, base, include_base, + BDRV_WANT_ALLOCATED, offset, bytes, pnum, NULL, NUL= L, &depth); if (ret < 0) { @@ -3709,8 +3710,8 @@ bdrv_co_preadv_snapshot(BdrvChild *child, int64_t off= set, int64_t bytes, } int coroutine_fn -bdrv_co_snapshot_block_status(BlockDriverState *bs, - bool want_zero, int64_t offset, int64_t byte= s, +bdrv_co_snapshot_block_status(BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { @@ -3728,7 +3729,7 @@ bdrv_co_snapshot_block_status(BlockDriverState *bs, } bdrv_inc_in_flight(bs); - ret =3D drv->bdrv_co_snapshot_block_status(bs, want_zero, offset, byte= s, + ret =3D drv->bdrv_co_snapshot_block_status(bs, mode, offset, bytes, pnum, map, file); bdrv_dec_in_flight(bs); diff --git a/block/blkdebug.c b/block/blkdebug.c index 1c1967f8e0a..c54aee0c84b 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -751,9 +751,9 @@ blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offs= et, int64_t bytes) } static int coroutine_fn GRAPH_RDLOCK -blkdebug_co_block_status(BlockDriverState *bs, bool want_zero, int64_t off= set, - int64_t bytes, int64_t *pnum, int64_t *map, - BlockDriverState **file) +blkdebug_co_block_status(BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file) { int err; diff --git a/block/copy-before-write.c b/block/copy-before-write.c index fd470f5f926..2badb3a8856 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -291,8 +291,8 @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t of= fset, int64_t bytes, } static int coroutine_fn GRAPH_RDLOCK -cbw_co_snapshot_block_status(BlockDriverState *bs, - bool want_zero, int64_t offset, int64_t bytes, +cbw_co_snapshot_block_status(BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { diff --git a/block/file-posix.c b/block/file-posix.c index 56d1972d156..91deb5bf5af 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -3201,7 +3201,7 @@ static int find_allocation(BlockDriverState *bs, off_= t start, * well exceed it. */ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, - bool want_zero, + unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, @@ -3217,7 +3217,7 @@ static int coroutine_fn raw_co_block_status(BlockDriv= erState *bs, return ret; } - if (!want_zero) { + if (mode !=3D BDRV_WANT_PRECISE) { *pnum =3D bytes; *map =3D offset; *file =3D bs; diff --git a/block/gluster.c b/block/gluster.c index c6d25ae7335..8197b0ecefa 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -1465,7 +1465,7 @@ exit: * (Based on raw_co_block_status() from file-posix.c.) */ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs, - bool want_zero, + unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, @@ -1482,7 +1482,7 @@ static int coroutine_fn qemu_gluster_co_block_status(= BlockDriverState *bs, return ret; } - if (!want_zero) { + if (mode !=3D BDRV_WANT_PRECISE) { *pnum =3D bytes; *map =3D offset; *file =3D bs; diff --git a/block/iscsi.c b/block/iscsi.c index 2f0f4dac097..15b96ee8800 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -694,9 +694,9 @@ out_unlock: static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs, - bool want_zero, int64_t offs= et, - int64_t bytes, int64_t *pnum, - int64_t *map, + unsigned int mode, + int64_t offset, int64_t byte= s, + int64_t *pnum, int64_t *map, BlockDriverState **file) { IscsiLun *iscsilun =3D bs->opaque; diff --git a/block/nbd.c b/block/nbd.c index 887841bc813..d5a2b21c6d1 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -1397,8 +1397,8 @@ nbd_client_co_pdiscard(BlockDriverState *bs, int64_t = offset, int64_t bytes) } static int coroutine_fn GRAPH_RDLOCK nbd_client_co_block_status( - BlockDriverState *bs, bool want_zero, int64_t offset, int64_t byte= s, - int64_t *pnum, int64_t *map, BlockDriverState **file) + BlockDriverState *bs, unsigned int mode, int64_t offset, + int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **fil= e) { int ret, request_ret; NBDExtent64 extent =3D { 0 }; diff --git a/block/null.c b/block/null.c index dc0b1fdbd9b..4e448d593d7 100644 --- a/block/null.c +++ b/block/null.c @@ -227,9 +227,9 @@ static int null_reopen_prepare(BDRVReopenState *reopen_= state, } static int coroutine_fn null_co_block_status(BlockDriverState *bs, - bool want_zero, int64_t offse= t, - int64_t bytes, int64_t *pnum, - int64_t *map, + unsigned int mode, + int64_t offset, int64_t bytes, + int64_t *pnum, int64_t *map, BlockDriverState **file) { BDRVNullState *s =3D bs->opaque; diff --git a/block/parallels.c b/block/parallels.c index 347ca127f34..3a375e2a8ab 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -416,9 +416,9 @@ parallels_co_flush_to_os(BlockDriverState *bs) } static int coroutine_fn GRAPH_RDLOCK -parallels_co_block_status(BlockDriverState *bs, bool want_zero, int64_t of= fset, - int64_t bytes, int64_t *pnum, int64_t *map, - BlockDriverState **file) +parallels_co_block_status(BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file) { BDRVParallelsState *s =3D bs->opaque; int count; diff --git a/block/qcow.c b/block/qcow.c index da8ad4d2430..8a3e7591a92 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -530,7 +530,7 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offse= t, int allocate, } static int coroutine_fn GRAPH_RDLOCK -qcow_co_block_status(BlockDriverState *bs, bool want_zero, +qcow_co_block_status(BlockDriverState *bs, unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { diff --git a/block/qcow2.c b/block/qcow2.c index 7774e7f0909..66fba89b414 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2141,9 +2141,9 @@ static void qcow2_join_options(QDict *options, QDict = *old_options) } static int coroutine_fn GRAPH_RDLOCK -qcow2_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, - int64_t count, int64_t *pnum, int64_t *map, - BlockDriverState **file) +qcow2_co_block_status(BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t count, int64_t *pnum, + int64_t *map, BlockDriverState **file) { BDRVQcow2State *s =3D bs->opaque; uint64_t host_offset; diff --git a/block/qed.c b/block/qed.c index ac24449ffb3..4a36fb39294 100644 --- a/block/qed.c +++ b/block/qed.c @@ -833,9 +833,9 @@ fail: } static int coroutine_fn GRAPH_RDLOCK -bdrv_qed_co_block_status(BlockDriverState *bs, bool want_zero, int64_t pos, - int64_t bytes, int64_t *pnum, int64_t *map, - BlockDriverState **file) +bdrv_qed_co_block_status(BlockDriverState *bs, unsigned int mode, + int64_t pos, int64_t bytes, int64_t *pnum, + int64_t *map, BlockDriverState **file) { BDRVQEDState *s =3D bs->opaque; size_t len =3D MIN(bytes, SIZE_MAX); diff --git a/block/quorum.c b/block/quorum.c index 30747a6df93..ed8ce801ee3 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1226,7 +1226,7 @@ static void quorum_child_perm(BlockDriverState *bs, B= drvChild *c, * region contains zeroes, and BDRV_BLOCK_DATA otherwise. */ static int coroutine_fn GRAPH_RDLOCK -quorum_co_block_status(BlockDriverState *bs, bool want_zero, +quorum_co_block_status(BlockDriverState *bs, unsigned int mode, int64_t offset, int64_t count, int64_t *pnum, int64_t *map, BlockDriverState **fil= e) { @@ -1238,7 +1238,7 @@ quorum_co_block_status(BlockDriverState *bs, bool wan= t_zero, for (i =3D 0; i < s->num_children; i++) { int64_t bytes; ret =3D bdrv_co_common_block_status_above(s->children[i]->bs, NULL= , false, - want_zero, offset, count, + mode, offset, count, &bytes, NULL, NULL, NULL); if (ret < 0) { quorum_report_bad(QUORUM_OP_TYPE_READ, offset, count, diff --git a/block/raw-format.c b/block/raw-format.c index e08526e2eca..df16ac1ea25 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -283,8 +283,8 @@ fail: } static int coroutine_fn GRAPH_RDLOCK -raw_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, - int64_t bytes, int64_t *pnum, int64_t *map, +raw_co_block_status(BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t bytes, int64_t *pnum, int64_t = *map, BlockDriverState **file) { BDRVRawState *s =3D bs->opaque; diff --git a/block/rbd.c b/block/rbd.c index af984fb7db4..4f3d42a8e7f 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1504,9 +1504,9 @@ static int qemu_rbd_diff_iterate_cb(uint64_t offs, si= ze_t len, } static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs, - bool want_zero, int64_t o= ffset, - int64_t bytes, int64_t *p= num, - int64_t *map, + unsigned int mode, + int64_t offset, int64_t b= ytes, + int64_t *pnum, int64_t *m= ap, BlockDriverState **file) { BDRVRBDState *s =3D bs->opaque; diff --git a/block/snapshot-access.c b/block/snapshot-access.c index 71ac83c01f0..17ed2402db8 100644 --- a/block/snapshot-access.c +++ b/block/snapshot-access.c @@ -41,11 +41,11 @@ snapshot_access_co_preadv_part(BlockDriverState *bs, static int coroutine_fn GRAPH_RDLOCK snapshot_access_co_block_status(BlockDriverState *bs, - bool want_zero, int64_t offset, + unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { - return bdrv_co_snapshot_block_status(bs->file->bs, want_zero, offset, + return bdrv_co_snapshot_block_status(bs->file->bs, mode, offset, bytes, pnum, map, file); } diff --git a/block/vdi.c b/block/vdi.c index a2da6ecab01..3ddc62a5690 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -523,8 +523,8 @@ static int vdi_reopen_prepare(BDRVReopenState *state, } static int coroutine_fn GRAPH_RDLOCK -vdi_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset, - int64_t bytes, int64_t *pnum, int64_t *map, +vdi_co_block_status(BlockDriverState *bs, unsigned int mode, + int64_t offset, int64_t bytes, int64_t *pnum, int64_t = *map, BlockDriverState **file) { BDRVVdiState *s =3D (BDRVVdiState *)bs->opaque; diff --git a/block/vmdk.c b/block/vmdk.c index 2adec499122..9c7ab037e14 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1777,7 +1777,7 @@ static inline uint64_t vmdk_find_offset_in_cluster(Vm= dkExtent *extent, } static int coroutine_fn GRAPH_RDLOCK -vmdk_co_block_status(BlockDriverState *bs, bool want_zero, +vmdk_co_block_status(BlockDriverState *bs, unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) { diff --git a/block/vpc.c b/block/vpc.c index 0309e319f60..801ff5793f8 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -726,7 +726,7 @@ fail: } static int coroutine_fn GRAPH_RDLOCK -vpc_co_block_status(BlockDriverState *bs, bool want_zero, +vpc_co_block_status(BlockDriverState *bs, unsigned int mode, int64_t offset, int64_t bytes, int64_t *pnum, int64_t *map, BlockDriverState **file) diff --git a/block/vvfat.c b/block/vvfat.c index 91d69b3cc83..814796d9185 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -3134,9 +3134,9 @@ vvfat_co_pwritev(BlockDriverState *bs, int64_t offset= , int64_t bytes, } static int coroutine_fn vvfat_co_block_status(BlockDriverState *bs, - bool want_zero, int64_t offs= et, - int64_t bytes, int64_t *n, - int64_t *map, + unsigned int mode, + int64_t offset, int64_t byte= s, + int64_t *n, int64_t *map, BlockDriverState **file) { *n =3D bytes; diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothr= ead.c index 2b358eaaa82..e26b3be5939 100644 --- a/tests/unit/test-block-iothread.c +++ b/tests/unit/test-block-iothread.c @@ -63,7 +63,7 @@ bdrv_test_co_truncate(BlockDriverState *bs, int64_t offse= t, bool exact, } static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs, - bool want_zero, + unsigned int mode, int64_t offset, int64_t = count, int64_t *pnum, int64_t *= map, BlockDriverState **file) --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542559; cv=none; d=zohomail.com; s=zohoarc; b=e/YuvmvHKHF7UnW6uvthrkL+azfqKg1dqJz1ZavHsqUCQlv5zJedY4ZxHx0fyaUg8LqcrPG/3lPvX9GpLLcJ1Bd6tw0f8kdra2MZ8p2cAu3wLTA6BRSEOTmtlW0eGEp1Rq6eyo6HCDbYZlxUdCTnFR/K0jpnFWgrN10DsxQRyu0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542559; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=JaGTuPEmX5rOSuL4+9zpLTiq+C9KVG7NUS6X5jCVdks=; b=PQPwCy+p6GwCLeRTdkrhjVKzmAII9nW3uBpcV29A9cQSwIhZ/n75tyHOKipazU6cJfQfUk6dU8djwRJmBufRr1AawI6WGX/CFVMTMF0VTE033zCmQzKRCLePiie0xJx+F8xz3AXIGm19Wdx6HlAqKt30fcW3m2lAm6XlICEfLJM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542559887454.2907682099817; Thu, 24 Apr 2025 17:55:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87LT-0006Vb-PF; Thu, 24 Apr 2025 20:55:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LR-0006Sj-BU for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:09 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LP-0000iA-Nj for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:09 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-216-A2ZK5ZcfNTGTtY4rTRnNVA-1; Thu, 24 Apr 2025 20:55:03 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E92B0180048E; Fri, 25 Apr 2025 00:55:00 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DA1B318001EF; Fri, 25 Apr 2025 00:54:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542507; 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=JaGTuPEmX5rOSuL4+9zpLTiq+C9KVG7NUS6X5jCVdks=; b=XtBwLCB2nOCAl8+S29J8q1wFLjD8U4ilW6QynmfwQrfiuWDsyaCrsmMBYXdo0E39inKQ+T 60k943K2dhGrT3U8dMPLGWSBcIocYhcea9swGk4w49Z72sLrUu3cuvmGkzVvfqBbPZG2n+ csW+XK2Y5spjBKRXgmDNe9RVbW1l3nM= X-MC-Unique: A2ZK5ZcfNTGTtY4rTRnNVA-1 X-Mimecast-MFC-AGG-ID: A2ZK5ZcfNTGTtY4rTRnNVA_1745542502 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Kevin Wolf , Hanna Reitz , integration@gluster.org (open list:GLUSTER) Subject: [PATCH v3 02/11] file-posix, gluster: Handle zero block status hint better Date: Thu, 24 Apr 2025 19:52:02 -0500 Message-ID: <20250425005439.2252467-15-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542562812019100 Content-Type: text/plain; charset="utf-8" Although the previous patch to change 'bool want_zero' into a bitmask made no semantic change, it is now time to differentiate. When the caller specifically wants to know what parts of the file read as zero, we need to use lseek and actually reporting holes, rather than short-circuiting and advertising full allocation. This change will be utilized in later patches to let mirroring optimize for the case when the destination already reads as zeroes. Signed-off-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- block/file-posix.c | 3 ++- block/gluster.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index 91deb5bf5af..575cbfba07d 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -3217,7 +3217,8 @@ static int coroutine_fn raw_co_block_status(BlockDriv= erState *bs, return ret; } - if (mode !=3D BDRV_WANT_PRECISE) { + if (!(mode & BDRV_WANT_ZERO)) { + /* There is no backing file - all bytes are allocated in this file= . */ *pnum =3D bytes; *map =3D offset; *file =3D bs; diff --git a/block/gluster.c b/block/gluster.c index 8197b0ecefa..e702666cbce 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -1482,7 +1482,7 @@ static int coroutine_fn qemu_gluster_co_block_status(= BlockDriverState *bs, return ret; } - if (mode !=3D BDRV_WANT_PRECISE) { + if (!(mode & BDRV_WANT_ZERO)) { *pnum =3D bytes; *map =3D offset; *file =3D bs; --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542617; cv=none; d=zohomail.com; s=zohoarc; b=XoOL3Y2tlNnetupoJ1DEFTNPQPyQINq0LtTHq1UUB7rYe9xo5281J++/kB/B6JoPIfb1Y0hottpxBYTgYOa5pIzaNK2v9JVZ9iiC1psyiZSpGyedT22i517PldEwGilgKhqH/wXc5YG/pNaiULBoOq3GZmCo8JhXDSQFL1xNw8c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542617; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=mp8jz+1BcXAdMIlc1C2i9pFAxzOJBCrZpHHsY/LwbF8=; b=mQooGMESCECYl8dMd5JnhG1SHT0IRmsVOxHHQahobHPyuSeqUPcfFXaNY8pXo4gQEVnb/L96gA1Pt6VzvyaUYC1AlsVCXrf/z888M3cO3JlHyfDMNSmuaQ+IBQbe6A8r7t6blupgo1PzWfx1RsYloyYS6Y785B/MHXm4fnxMJCk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 174554261715334.36074674788381; Thu, 24 Apr 2025 17:56:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87LX-0006bS-KE; Thu, 24 Apr 2025 20:55:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LS-0006V1-HP for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:10 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LQ-0000i4-0E for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:10 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-119-JjXkulD3OyCak1KbLUJlng-1; Thu, 24 Apr 2025 20:55:04 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3B4DB1956088; Fri, 25 Apr 2025 00:55:03 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5A40E1800378; Fri, 25 Apr 2025 00:55:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542506; 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=mp8jz+1BcXAdMIlc1C2i9pFAxzOJBCrZpHHsY/LwbF8=; b=M+NUYap5YEQHZgFqV2En2aJAIAVQ3aYshSzVGTRJHf4x27nK396TskAz99CuFSYoGZbxNK MNqlRNJ/l7ds/bc7eL3++ALl5QvkN8VZZEkJpPHYt3zATwfzJJxsBWhpsuJaKKdtPnoVn9 QTEr2J4Yw91PYPWOchG8AjGRIXgvcXA= X-MC-Unique: JjXkulD3OyCak1KbLUJlng-1 X-Mimecast-MFC-AGG-ID: JjXkulD3OyCak1KbLUJlng_1745542503 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Fam Zheng , Kevin Wolf , Hanna Reitz Subject: [PATCH v3 03/11] block: Let bdrv_co_is_zero_fast consolidate adjacent extents Date: Thu, 24 Apr 2025 19:52:03 -0500 Message-ID: <20250425005439.2252467-16-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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.129.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542618984019100 Content-Type: text/plain; charset="utf-8" Some BDS drivers have a cap on how much block status they can supply in one query (for example, NBD talking to an older server cannot inspect more than 4G per query; and qcow2 tends to cap its answers rather than cross a cluster boundary of an L1 table). Although the existing callers of bdrv_co_is_zero_fast are not passing in that large of a 'bytes' parameter, an upcoming caller wants to query the entire image at once, and will thus benefit from being able to treat adjacent zero regions in a coalesced manner, rather than claiming the region is non-zero merely because pnum was truncated and didn't match the incoming bytes. While refactoring this into a loop, note that there is no need to assign pnum prior to calling bdrv_co_common_block_status_above() (it is guaranteed to be assigned deeper in the callstack). Signed-off-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- v3: also tweak function comment --- block/io.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/block/io.c b/block/io.c index 056af8198bc..d3bd1211acf 100644 --- a/block/io.c +++ b/block/io.c @@ -2751,28 +2751,31 @@ int coroutine_fn bdrv_co_block_status(BlockDriverSt= ate *bs, int64_t offset, * by @offset and @bytes is known to read as zeroes. * Return 1 if that is the case, 0 otherwise and -errno on error. * This test is meant to be fast rather than accurate so returning 0 - * does not guarantee non-zero data. + * does not guarantee non-zero data; but a return of 1 is reliable. */ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes) { int ret; - int64_t pnum =3D bytes; + int64_t pnum; IO_CODE(); - if (!bytes) { - return 1; + while (bytes) { + ret =3D bdrv_co_common_block_status_above(bs, NULL, false, + BDRV_WANT_ZERO, offset, by= tes, + &pnum, NULL, NULL, NULL); + + if (ret < 0) { + return ret; + } + if (!(ret & BDRV_BLOCK_ZERO)) { + return 0; + } + offset +=3D pnum; + bytes -=3D pnum; } - ret =3D bdrv_co_common_block_status_above(bs, NULL, false, BDRV_WANT_Z= ERO, - offset, bytes, &pnum, NULL, NU= LL, - NULL); - - if (ret < 0) { - return ret; - } - - return (pnum =3D=3D bytes) && (ret & BDRV_BLOCK_ZERO); + return 1; } int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542579; cv=none; d=zohomail.com; s=zohoarc; b=X7T8XosCyzLlBBGu/JNebgOQjjnHJw/aVaeve2LZ43OpULPNVI+i5446WiYKoboFEErtTNO2qXUWViX3T2uW3InPH0fsD0cOT4lOOOQzi6iSSN8P8NInI6wbV7+UCb8qwu2/sR4MVFI4KuqVIUzpKDbfI1zq4w/FRPBGbWF8vKE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542579; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=0ZzpfKx3C6m143Gj6EaaLAs5VPN4mDYMTZDD3BLasyo=; b=mv0yQeQVghxTvjkpur1a81IGGpLrpMWUk1XsMb5ean4j1uc93sJ0ITcLnysvLBjh93RtTjAJc93XHV/D5GDwv8twXv8nVWsxOqHQSBE6p4UNC3ZpifIXFM0iwLrjtvVTlkzN9GKVgwaLO3EDLSkAYhmB9nf2zj3DgPH0nD0p0MQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542579422813.9093461653318; Thu, 24 Apr 2025 17:56:19 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87LW-0006aN-19; Thu, 24 Apr 2025 20:55:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LT-0006Vl-76 for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:11 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LR-0000jE-Dl for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:10 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-530-mOmQ3vtrPVO596qqOIsFew-1; Thu, 24 Apr 2025 20:55:07 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8CAA21956086; Fri, 25 Apr 2025 00:55:05 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9D48A1800374; Fri, 25 Apr 2025 00:55:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542508; 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=0ZzpfKx3C6m143Gj6EaaLAs5VPN4mDYMTZDD3BLasyo=; b=h9w+OasKVokuUTuhg+lxi7iKEZ1m/qczxIOyFJBHxVWp9t8wXQUA/ytaTyeMDzbJekxaOF laz00pJ7mOy0NX/AHCCl6OlTtZv3CqBmrCdmBAQBK9SX2wQdmblTZiegol1rp2DrrI5qQ0 mJ6Pf5aZJ1vcAPefIocEnQdeGZOPy/A= X-MC-Unique: mOmQ3vtrPVO596qqOIsFew-1 X-Mimecast-MFC-AGG-ID: mOmQ3vtrPVO596qqOIsFew_1745542506 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Fam Zheng , Kevin Wolf , Hanna Reitz Subject: [PATCH v3 04/11] block: Add new bdrv_co_is_all_zeroes() function Date: Thu, 24 Apr 2025 19:52:04 -0500 Message-ID: <20250425005439.2252467-17-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542582099019100 Content-Type: text/plain; charset="utf-8" There are some optimizations that require knowing if an image starts out as reading all zeroes, such as making blockdev-mirror faster by skipping the copying of source zeroes to the destination. The existing bdrv_co_is_zero_fast() is a good building block for answering this question, but it tends to give an answer of 0 for a file we just created via QMP 'blockdev-create' or similar (such as 'qemu-img create -f raw'). Why? Because file-posix.c insists on allocating a tiny header to any file rather than leaving it 100% sparse, due to some filesystems that are unable to answer alignment probes on a hole. But teaching file-posix.c to read the tiny header doesn't scale - the problem of a small header is also visible when libvirt sets up an NBD client to a just-created file on a migration destination host. So, we need a wrapper function that handles a bit more complexity in a common manner for all block devices - when the BDS is mostly a hole, but has a small non-hole header, it is still worth the time to read that header and check if it reads as all zeroes before giving up and returning a pessimistic answer. Signed-off-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- v3: Use constant 128k as maximum data header size to read [Stefan] --- include/block/block-io.h | 2 ++ block/io.c | 62 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/include/block/block-io.h b/include/block/block-io.h index b49e0537dd4..b99cc98d265 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -161,6 +161,8 @@ bdrv_is_allocated_above(BlockDriverState *bs, BlockDriv= erState *base, int coroutine_fn GRAPH_RDLOCK bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset, int64_t bytes); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_is_all_zeroes(BlockDriverState *bs); int GRAPH_RDLOCK bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg, diff --git a/block/io.c b/block/io.c index d3bd1211acf..69da64c5915 100644 --- a/block/io.c +++ b/block/io.c @@ -38,10 +38,14 @@ #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "system/replay.h" +#include "qemu/units.h" /* Maximum bounce buffer for copy-on-read and write zeroes, in bytes */ #define MAX_BOUNCE_BUFFER (32768 << BDRV_SECTOR_BITS) +/* Maximum read size for checking if data reads as zero, in bytes */ +#define MAX_ZERO_CHECK_BUFFER (128 * KiB) + static void coroutine_fn GRAPH_RDLOCK bdrv_parent_cb_resize(BlockDriverState *bs); @@ -2778,6 +2782,64 @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverSta= te *bs, int64_t offset, return 1; } +/* + * Check @bs (and its backing chain) to see if the entire image is known + * to read as zeroes. + * Return 1 if that is the case, 0 otherwise and -errno on error. + * This test is meant to be fast rather than accurate so returning 0 + * does not guarantee non-zero data; however, a return of 1 is reliable, + * and this function can report 1 in more cases than bdrv_co_is_zero_fast. + */ +int coroutine_fn bdrv_co_is_all_zeroes(BlockDriverState *bs) +{ + int ret; + int64_t pnum, bytes; + char *buf; + QEMUIOVector local_qiov; + IO_CODE(); + + bytes =3D bdrv_co_getlength(bs); + if (bytes < 0) { + return bytes; + } + + /* First probe - see if the entire image reads as zero */ + ret =3D bdrv_co_common_block_status_above(bs, NULL, false, BDRV_WANT_Z= ERO, + 0, bytes, &pnum, NULL, NULL, + NULL); + if (ret < 0) { + return ret; + } + if (ret & BDRV_BLOCK_ZERO) { + return bdrv_co_is_zero_fast(bs, pnum, bytes - pnum); + } + + /* + * Because of the way 'blockdev-create' works, raw files tend to + * be created with a non-sparse region at the front to make + * alignment probing easier. If the block starts with only a + * small allocated region, it is still worth the effort to see if + * the rest of the image is still sparse, coupled with manually + * reading the first region to see if it reads zero after all. + */ + if (pnum > MAX_ZERO_CHECK_BUFFER) { + return 0; + } + ret =3D bdrv_co_is_zero_fast(bs, pnum, bytes - pnum); + if (ret <=3D 0) { + return ret; + } + /* Only the head of the image is unknown, and it's small. Read it. */ + buf =3D qemu_blockalign(bs, pnum); + qemu_iovec_init_buf(&local_qiov, buf, pnum); + ret =3D bdrv_driver_preadv(bs, 0, pnum, &local_qiov, 0, 0); + if (ret >=3D 0) { + ret =3D buffer_is_zero(buf, pnum); + } + qemu_vfree(buf); + return ret; +} + int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t *pnum) { --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542637; cv=none; d=zohomail.com; s=zohoarc; b=C9eZ9dbl6bFADjWXXuNF++LUYi2NmPXoR7Sryf9lHXS0DNIdWP3gOmF+ZKgtyVkARRjkmZBVjmcAYPYSIP3V/nBCN57T/M0uabj3vNJQqFN2FL8hnA6Na+5Ap/AEAZy8B7kFpvVb+LuitXG5KD2W+7xzlr5geD+IPzOZ6uTDO3U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542637; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/5vYFny3KY+YPBZUlV2L+qBrM5argzflEf5xqcWdd8k=; b=i81Egqt/d1Dy4a4hdBrdHAKHGw6Gd8mboPdSh++CDlDOnD2Z+BNurrQAR4g85oS806Z1WBBK2SKOjTv7hsTKZLDVGOyBxxNmA6VXOZNZQw+rlCBeICnCchw6LxAFW2zWZvTdO7+AcdbVg+srQJ7OJZ4tMVuMHaSUC0vToDvgsdA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542637687543.7270563957413; Thu, 24 Apr 2025 17:57:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87LZ-0006iD-9v; Thu, 24 Apr 2025 20:55:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LW-0006ao-BX for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:14 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LU-0000kx-Ue for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:14 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-230-Kx26B9gFP-20QDggKerrvw-1; Thu, 24 Apr 2025 20:55:08 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 941911800875; Fri, 25 Apr 2025 00:55:07 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E955A18001EF; Fri, 25 Apr 2025 00:55:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542512; 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=/5vYFny3KY+YPBZUlV2L+qBrM5argzflEf5xqcWdd8k=; b=NuUAFTDZJUV1JMuk5+uU4zeVT7CKlRAgSenH5DBraSpPduTLoMN5OeqzIYUMuh90MvOIHg 00TOhSmWpjtq7Of77sm4fmGU0qQHt6/L0x7CseisJ44o9R5hmvjmLxVf57g59+W64vxpHq TK601u47RmUWPEyw1pyd8ITKuuo+EvI= X-MC-Unique: Kx26B9gFP-20QDggKerrvw-1 X-Mimecast-MFC-AGG-ID: Kx26B9gFP-20QDggKerrvw_1745542507 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Kevin Wolf , Hanna Reitz Subject: [PATCH v3 05/11] iotests: Improve iotest 194 to mirror data Date: Thu, 24 Apr 2025 19:52:05 -0500 Message-ID: <20250425005439.2252467-18-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542642246019100 Content-Type: text/plain; charset="utf-8" Mirroring a completely sparse image to a sparse destination should be practically instantaneous. It isn't yet, but the test will be more realistic if it has some non-zero to mirror as well as the holes. Signed-off-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- tests/qemu-iotests/194 | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 index c0ce82dd257..d0b9c084f5f 100755 --- a/tests/qemu-iotests/194 +++ b/tests/qemu-iotests/194 @@ -34,6 +34,7 @@ with iotests.FilePath('source.img') as source_img_path, \ img_size =3D '1G' iotests.qemu_img_create('-f', iotests.imgfmt, source_img_path, img_siz= e) + iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write 512M 1M', source_im= g_path) iotests.qemu_img_create('-f', iotests.imgfmt, dest_img_path, img_size) iotests.log('Launching VMs...') --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542548; cv=none; d=zohomail.com; s=zohoarc; b=l7o9waAAQf3DlUSj+rSf9B/aEeNLHRpE0gFyzDdpcFYsNmHMWwWglEEX/uVG49ib4RYVZ+nnCanpFwtMTH0yXPThbBFrL2MjR0SML2yMgY89PYJkysOo6W5WEw5AW82L5zgia4NLemkMS9ZCy4B+ip/M03Wv4AfkOyKT/MeY0aI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542548; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Wn6zBuqpNVmvcfbdxpgMz2X9n+bh2itxCd5KFp+3S5M=; b=Fm/nwe/w2mEiHR2+L101in70zXYaRIAAMAshbtEJHRb+/u4C4wz+78Qb5PJL4/tJqNuLGebMzFbpGfcCzsHAjrbmH7DePy7h9hPo8jf7VCNxVrMtzuFwq9aeKug9RDMi1JFLhxHQ4YKPeWa2//pM00oLiuATW3Wuy7pvw5lpTvw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542548612373.7831941959521; Thu, 24 Apr 2025 17:55:48 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87Lb-0006nN-Ps; Thu, 24 Apr 2025 20:55:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LX-0006et-NQ for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:15 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LV-0000lC-TL for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:15 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-629-_GJZ2hz_M9WZRMCRouLacQ-1; Thu, 24 Apr 2025 20:55:10 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id AB29C180036D; Fri, 25 Apr 2025 00:55:09 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0032A1800374; Fri, 25 Apr 2025 00:55:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542513; 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=Wn6zBuqpNVmvcfbdxpgMz2X9n+bh2itxCd5KFp+3S5M=; b=YTQYO3HhWTBK27EvvSxqwg7qVKQzquCf2Ihmx6UHt5Nv5JG/5xe+rGU67qbVR7yZ+cx+Dw LAlv4ZwIRfdKecJO2XWlmE9HHm2fA8h0MfFsewxmqIkUT58vEysQ5Bn3hPUKGJMahSGO1e hBlcuJrKNxKwbcKrp7Oo/9vBijsc19w= X-MC-Unique: _GJZ2hz_M9WZRMCRouLacQ-1 X-Mimecast-MFC-AGG-ID: _GJZ2hz_M9WZRMCRouLacQ_1745542509 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, John Snow , Kevin Wolf , Hanna Reitz Subject: [PATCH v3 06/11] mirror: Minor refactoring Date: Thu, 24 Apr 2025 19:52:06 -0500 Message-ID: <20250425005439.2252467-19-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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.129.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542550989019000 Content-Type: text/plain; charset="utf-8" Commit 5791ba52 (v9.2) pre-initialized ret in mirror_dirty_init to silence a false positive compiler warning, even though in all code paths where ret is used, it was guaranteed to be reassigned beforehand. But since the function returns -errno, and -1 is not always the right errno, it's better to initialize to -EIO. An upcoming patch wants to track two bitmaps in do_sync_target_write(); this will be easier if the current variables related to the dirty bitmap are renamed. Signed-off-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- block/mirror.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index a53582f17bb..34c6c5252e1 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -841,7 +841,7 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_ini= t(MirrorBlockJob *s) int64_t offset; BlockDriverState *bs; BlockDriverState *target_bs =3D blk_bs(s->target); - int ret =3D -1; + int ret =3D -EIO; int64_t count; bdrv_graph_co_rdlock(); @@ -1341,7 +1341,7 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMetho= d method, { int ret; size_t qiov_offset =3D 0; - int64_t bitmap_offset, bitmap_end; + int64_t dirty_bitmap_offset, dirty_bitmap_end; if (!QEMU_IS_ALIGNED(offset, job->granularity) && bdrv_dirty_bitmap_get(job->dirty_bitmap, offset)) @@ -1388,11 +1388,11 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMet= hod method, * Tails are either clean or shrunk, so for bitmap resetting * we safely align the range down. */ - bitmap_offset =3D QEMU_ALIGN_UP(offset, job->granularity); - bitmap_end =3D QEMU_ALIGN_DOWN(offset + bytes, job->granularity); - if (bitmap_offset < bitmap_end) { - bdrv_reset_dirty_bitmap(job->dirty_bitmap, bitmap_offset, - bitmap_end - bitmap_offset); + dirty_bitmap_offset =3D QEMU_ALIGN_UP(offset, job->granularity); + dirty_bitmap_end =3D QEMU_ALIGN_DOWN(offset + bytes, job->granularity); + if (dirty_bitmap_offset < dirty_bitmap_end) { + bdrv_reset_dirty_bitmap(job->dirty_bitmap, dirty_bitmap_offset, + dirty_bitmap_end - dirty_bitmap_offset); } job_progress_increase_remaining(&job->common.job, bytes); @@ -1430,10 +1430,10 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMet= hod method, * at function start, and they must be still dirty, as we've locked * the region for in-flight op. */ - bitmap_offset =3D QEMU_ALIGN_DOWN(offset, job->granularity); - bitmap_end =3D QEMU_ALIGN_UP(offset + bytes, job->granularity); - bdrv_set_dirty_bitmap(job->dirty_bitmap, bitmap_offset, - bitmap_end - bitmap_offset); + dirty_bitmap_offset =3D QEMU_ALIGN_DOWN(offset, job->granularity); + dirty_bitmap_end =3D QEMU_ALIGN_UP(offset + bytes, job->granularit= y); + bdrv_set_dirty_bitmap(job->dirty_bitmap, dirty_bitmap_offset, + dirty_bitmap_end - dirty_bitmap_offset); qatomic_set(&job->actively_synced, false); action =3D mirror_error_action(job, false, -ret); --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542534; cv=none; d=zohomail.com; s=zohoarc; b=P+uZ+CFCS6mGS7iXUq3Lhtc/q0TOeNKmwPE5opFdQQQ+46uswxfWMzUaoaNSnxhLwt3PsnxtILHr/xc9tMMNvIyoUxQLwYnCzE2pBhhTgUwbld78b+R04Xn1T7QH3YCLN/xmhWehgpLHPhRs6IQNoxi5i8u0psVyE5sSZI63iTk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542534; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XxqVYIlN1ZlXcezHFPpFEZRs19Uzw4DTzoZFCemFol4=; b=LigDvNEzDiQlbjT/1Gu7WiN6ALB4r4Jhr2rQLOkyJXSQqSeNOyyNZoI1ZREnuG66e6qyrcp2rPQf7JCB0Q83zZpMrYQEAufYMFZ6gSuKhuTqwAEzr5TePAUYsuUDcFkJ166rqQa57RFqk5HB8UbPHIP/bj+vx18sweXcVx2K8vk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542534243862.1294479115252; Thu, 24 Apr 2025 17:55:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87Le-0006wo-3S; Thu, 24 Apr 2025 20:55:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87La-0006mT-UV for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:19 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LZ-0000mQ-CN for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:18 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-372-6cBAjYN9NAqdX9bcYNpPjg-1; Thu, 24 Apr 2025 20:55:12 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A6A17195609D; Fri, 25 Apr 2025 00:55:11 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 15B7A1800378; Fri, 25 Apr 2025 00:55:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542516; 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=XxqVYIlN1ZlXcezHFPpFEZRs19Uzw4DTzoZFCemFol4=; b=SB67rW8wfk8GwJcLeHIw4CEb3HE4j2GiGE7yrfSyOOLYcgXtw2UcSZDl5m0Hsyyi4o0LAz i9ma/WAbtvnkN6AtaYB1cRHOTImFC9HiKcMocbtO0to+aya3Bj6/EKPNF+/+icTe/sKyRm mWfJ7YEOECBmu2TQ0R9m/pWthKe6njM= X-MC-Unique: 6cBAjYN9NAqdX9bcYNpPjg-1 X-Mimecast-MFC-AGG-ID: 6cBAjYN9NAqdX9bcYNpPjg_1745542511 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, John Snow , Kevin Wolf , Hanna Reitz Subject: [PATCH v3 07/11] mirror: Skip pre-zeroing destination if it is already zero Date: Thu, 24 Apr 2025 19:52:07 -0500 Message-ID: <20250425005439.2252467-20-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542536992019100 Content-Type: text/plain; charset="utf-8" When doing a sync=3Dfull mirroring, QMP drive-mirror requests full zeroing if it did not just create the destination, and blockdev-mirror requests full zeroing unconditionally. This is because during a full sync, we must ensure that the portions of the disk that are not otherwise touched by the source still read as zero upon completion. However, in mirror_dirty_init(), we were blindly assuming that if the destination allows punching holes, we should pre-zero the entire image; and if it does not allow punching holes, then treat the entire source as dirty rather than mirroring just the allocated portions of the source. Without the ability to punch holes, this results in the destination file being fully allocated; and even when punching holes is supported, it causes duplicate I/O to the portions of the destination corresponding to chunks of the source that are allocated but read as zero. Smarter is to avoid the pre-zeroing pass over the destination if it can be proved the destination already reads as zero. Note that a later patch will then further improve things to skip writing to the destination for parts of the image where the source is zero; but even with just this patch, it is possible to see a difference for any BDS that can quickly report that it already reads as zero. Note, however, that if the destination was opened with "detect-zeroes": "unmap", then the user wants us to punch holes where possible for any zeroes in the source; in that case, we are better off doing unmap up front in bulk. Signed-off-by: Eric Blake --- v3: add exemption for "detect-zeroes":"unmap" on destination --- block/mirror.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/block/mirror.c b/block/mirror.c index 34c6c5252e1..4059bf96854 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -849,13 +849,30 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_i= nit(MirrorBlockJob *s) bdrv_graph_co_rdunlock(); if (s->zero_target) { + offset =3D 0; + bdrv_graph_co_rdlock(); + ret =3D bdrv_co_is_all_zeroes(target_bs); + bdrv_graph_co_rdunlock(); + if (ret < 0) { + return ret; + } + /* + * If the destination already reads as zero, and we are not + * requested to punch holes into existing zeroes, then we can + * skip pre-zeroing the destination. + */ + if (ret > 0 && + (target_bs->detect_zeroes !=3D BLOCKDEV_DETECT_ZEROES_OPTIONS_= UNMAP || + !bdrv_can_write_zeroes_with_unmap(target_bs))) { + offset =3D s->bdev_length; + } if (!bdrv_can_write_zeroes_with_unmap(target_bs)) { bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length); return 0; } s->initial_zeroing_ongoing =3D true; - for (offset =3D 0; offset < s->bdev_length; ) { + while (offset < s->bdev_length) { int bytes =3D MIN(s->bdev_length - offset, QEMU_ALIGN_DOWN(INT_MAX, s->granularity)); --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542637; cv=none; d=zohomail.com; s=zohoarc; b=aYLKGwSatRudrYxs/yEHjE5IyLHwejX9iHIz3o/SuOkjixXzO/lgMD97u8lImHuHMBj/nsNrdi11OsanRD/2NteSKPOJAS6ubQf1S4Vbk0Ei8tBv4qlmEkg0FZz6gCGXstCyvIqIgp6g4swexHx8N667fBzP/cd6RKz+wI+/zbY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542637; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=hcDH9p6H/EPFu5ldQahTqYObeHljv+DZrkONSWOsJw0=; b=lEnQ50qNFzA/x3J+2VV8WOqo0lXCzFw/RVspUduCbKyrmIgcTtJWxJt+PsY+W9BOelLZrttHjiAa0TMXXZj6vaAICX7cLMXH9JOTGZsDk6Y4zvZF0DrslubcfMi2l+xvDRqpoOIfo2tHm9K9udFm3y03W7hFBjPTfbIWcsvotiw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542637698966.1442961810089; Thu, 24 Apr 2025 17:57:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87Le-0006ww-5i; Thu, 24 Apr 2025 20:55:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87Lb-0006ol-Nx for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:19 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87LZ-0000mY-I5 for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:19 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-29-805JznhsMg-ZAXJt96Cn_A-1; Thu, 24 Apr 2025 20:55:14 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D5272180036E; Fri, 25 Apr 2025 00:55:13 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 113081800374; Fri, 25 Apr 2025 00:55:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542516; 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=hcDH9p6H/EPFu5ldQahTqYObeHljv+DZrkONSWOsJw0=; b=L7WvsKV5apRWtyHZ96BUn7ND67GWRZmVKf1mdrcWeVdToIj+nRuIN9JVZO5qC1udkHt/C6 pfwDeCI7TM/n3N5iyjp0Pb/zG8V23N232f01Jyatig9FeObLIvGi0+bJ/bIFnqawfFRjBF 9CrMUzRNyQIdEfNRukhZrZsjwZD9m2g= X-MC-Unique: 805JznhsMg-ZAXJt96Cn_A-1 X-Mimecast-MFC-AGG-ID: 805JznhsMg-ZAXJt96Cn_A_1745542513 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, John Snow , Kevin Wolf , Hanna Reitz Subject: [PATCH v3 08/11] mirror: Skip writing zeroes when target is already zero Date: Thu, 24 Apr 2025 19:52:08 -0500 Message-ID: <20250425005439.2252467-21-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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.129.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542638770019000 Content-Type: text/plain; charset="utf-8" When mirroring, the goal is to ensure that the destination reads the same as the source; this goal is met whether the destination is sparse or fully-allocated. However, if the destination cannot efficiently write zeroes, then any time the mirror operation wants to copy zeroes from the source to the destination (either during the background over sparse regions when doing a full mirror, or in the foreground when the guest actively writes zeroes), we were causing the destination to fully allocate that portion of the disk, even if it already read as zeroes. The effect is especially pronounced when the source is a raw file. That's because when the source is a qcow2 file, the dirty bitmap only visits the portions of the source that are allocated, which tend to be non-zero. But when the source is a raw file, bdrv_co_is_allocated_above() reports the entire file as allocated so mirror_dirty_init sets the entire dirty bitmap, and it is only later during mirror_iteration that we change to consulting the more precise bdrv_co_block_status_above() to learn where the source reads as zero. Remember that since a mirror operation can write a cluster more than once (every time the guest changes the source, the destination is also changed to keep up), we can't take the shortcut of relying on s->zero_target (which is static for the life of the job) in mirror_co_zero() to see if the destination is already zero, because that information may be stale. Any solution we use must be dynamic in the face of the guest writing or discarding a cluster while the mirror has been ongoing. We could just teach mirror_co_zero() to do a block_status() probe of the destination, and skip the zeroes if the destination already reads as zero, but we know from past experience that extra block_status() calls are not always cheap (tmpfs, anyone?), especially when they are random access rather than linear. Use of block_status() of the source by the background task in a linear fashion is not our bottleneck (it's a background task, after all); but since mirroring can be done while the source is actively being changed, we don't want a slow block_status() of the destination to occur on the hot path of the guest trying to do random-access writes to the source. So this patch takes a slightly different approach: any time we have to transfer the full image, we know that mirror_dirty_init() is _already_ doing a pre-zero pass over the entire destination. Therefore, if we track which clusters of the destination are zero at any given moment, we don't have to do a block_status() call on the destination, but can instead just refer to the zero bitmap associated with the job. With this patch, if I create a raw sparse destination file, connect it with QMP 'blockdev-add' while leaving it at the default "discard": "ignore", then run QMP 'blockdev-mirror' with "sync": "full", the destination remains sparse rather than fully allocated. Meanwhile, a destination image that is already fully allocated remains so unless it was opened with "detect-zeroes": "unmap". If writing zeroes is skipped, the job counters are not incremented. Signed-off-by: Eric Blake --- v3: also skip counters when skipping I/O [Sunny] --- block/mirror.c | 92 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index 4059bf96854..69a02dfc2b7 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -73,6 +73,7 @@ typedef struct MirrorBlockJob { size_t buf_size; int64_t bdev_length; unsigned long *cow_bitmap; + unsigned long *zero_bitmap; BdrvDirtyBitmap *dirty_bitmap; BdrvDirtyBitmapIter *dbi; uint8_t *buf; @@ -108,9 +109,12 @@ struct MirrorOp { int64_t offset; uint64_t bytes; - /* The pointee is set by mirror_co_read(), mirror_co_zero(), and - * mirror_co_discard() before yielding for the first time */ + /* + * These pointers are set by mirror_co_read(), mirror_co_zero(), and + * mirror_co_discard() before yielding for the first time + */ int64_t *bytes_handled; + bool *io_skipped; bool is_pseudo_op; bool is_active_write; @@ -408,15 +412,34 @@ static void coroutine_fn mirror_co_read(void *opaque) static void coroutine_fn mirror_co_zero(void *opaque) { MirrorOp *op =3D opaque; - int ret; + bool write_needed =3D true; + int ret =3D 0; op->s->in_flight++; op->s->bytes_in_flight +=3D op->bytes; *op->bytes_handled =3D op->bytes; op->is_in_flight =3D true; - ret =3D blk_co_pwrite_zeroes(op->s->target, op->offset, op->bytes, - op->s->unmap ? BDRV_REQ_MAY_UNMAP : 0); + if (op->s->zero_bitmap) { + unsigned long end =3D DIV_ROUND_UP(op->offset + op->bytes, + op->s->granularity); + assert(QEMU_IS_ALIGNED(op->offset, op->s->granularity)); + assert(QEMU_IS_ALIGNED(op->bytes, op->s->granularity) || + op->offset + op->bytes =3D=3D op->s->bdev_length); + if (find_next_zero_bit(op->s->zero_bitmap, end, + op->offset / op->s->granularity) =3D=3D end= ) { + write_needed =3D false; + *op->io_skipped =3D true; + } + } + if (write_needed) { + ret =3D blk_co_pwrite_zeroes(op->s->target, op->offset, op->bytes, + op->s->unmap ? BDRV_REQ_MAY_UNMAP : 0); + } + if (ret >=3D 0 && op->s->zero_bitmap) { + bitmap_set(op->s->zero_bitmap, op->offset / op->s->granularity, + DIV_ROUND_UP(op->bytes, op->s->granularity)); + } mirror_write_complete(op, ret); } @@ -435,29 +458,43 @@ static void coroutine_fn mirror_co_discard(void *opaq= ue) } static unsigned mirror_perform(MirrorBlockJob *s, int64_t offset, - unsigned bytes, MirrorMethod mirror_method) + unsigned bytes, MirrorMethod mirror_method, + bool *io_skipped) { MirrorOp *op; Coroutine *co; int64_t bytes_handled =3D -1; + assert(QEMU_IS_ALIGNED(offset, s->granularity)); + assert(QEMU_IS_ALIGNED(bytes, s->granularity) || + offset + bytes =3D=3D s->bdev_length); op =3D g_new(MirrorOp, 1); *op =3D (MirrorOp){ .s =3D s, .offset =3D offset, .bytes =3D bytes, .bytes_handled =3D &bytes_handled, + .io_skipped =3D io_skipped, }; qemu_co_queue_init(&op->waiting_requests); switch (mirror_method) { case MIRROR_METHOD_COPY: + if (s->zero_bitmap) { + bitmap_clear(s->zero_bitmap, offset / s->granularity, + DIV_ROUND_UP(bytes, s->granularity)); + } co =3D qemu_coroutine_create(mirror_co_read, op); break; case MIRROR_METHOD_ZERO: + /* s->zero_bitmap handled in mirror_co_zero */ co =3D qemu_coroutine_create(mirror_co_zero, op); break; case MIRROR_METHOD_DISCARD: + if (s->zero_bitmap) { + bitmap_clear(s->zero_bitmap, offset / s->granularity, + DIV_ROUND_UP(bytes, s->granularity)); + } co =3D qemu_coroutine_create(mirror_co_discard, op); break; default: @@ -568,6 +605,7 @@ static void coroutine_fn GRAPH_UNLOCKED mirror_iteratio= n(MirrorBlockJob *s) int ret =3D -1; int64_t io_bytes; int64_t io_bytes_acct; + bool io_skipped =3D false; MirrorMethod mirror_method =3D MIRROR_METHOD_COPY; assert(!(offset % s->granularity)); @@ -611,8 +649,10 @@ static void coroutine_fn GRAPH_UNLOCKED mirror_iterati= on(MirrorBlockJob *s) } io_bytes =3D mirror_clip_bytes(s, offset, io_bytes); - io_bytes =3D mirror_perform(s, offset, io_bytes, mirror_method); - if (mirror_method !=3D MIRROR_METHOD_COPY && write_zeroes_ok) { + io_bytes =3D mirror_perform(s, offset, io_bytes, mirror_method, + &io_skipped); + if (io_skipped || + (mirror_method !=3D MIRROR_METHOD_COPY && write_zeroes_ok)) { io_bytes_acct =3D 0; } else { io_bytes_acct =3D io_bytes; @@ -849,6 +889,8 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_ini= t(MirrorBlockJob *s) bdrv_graph_co_rdunlock(); if (s->zero_target) { + int64_t bitmap_length =3D DIV_ROUND_UP(s->bdev_length, s->granular= ity); + offset =3D 0; bdrv_graph_co_rdlock(); ret =3D bdrv_co_is_all_zeroes(target_bs); @@ -856,6 +898,7 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_ini= t(MirrorBlockJob *s) if (ret < 0) { return ret; } + s->zero_bitmap =3D bitmap_new(bitmap_length); /* * If the destination already reads as zero, and we are not * requested to punch holes into existing zeroes, then we can @@ -864,6 +907,7 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_ini= t(MirrorBlockJob *s) if (ret > 0 && (target_bs->detect_zeroes !=3D BLOCKDEV_DETECT_ZEROES_OPTIONS_= UNMAP || !bdrv_can_write_zeroes_with_unmap(target_bs))) { + bitmap_set(s->zero_bitmap, 0, bitmap_length); offset =3D s->bdev_length; } if (!bdrv_can_write_zeroes_with_unmap(target_bs)) { @@ -875,6 +919,7 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_ini= t(MirrorBlockJob *s) while (offset < s->bdev_length) { int bytes =3D MIN(s->bdev_length - offset, QEMU_ALIGN_DOWN(INT_MAX, s->granularity)); + bool ignored; mirror_throttle(s); @@ -890,7 +935,7 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_ini= t(MirrorBlockJob *s) continue; } - mirror_perform(s, offset, bytes, MIRROR_METHOD_ZERO); + mirror_perform(s, offset, bytes, MIRROR_METHOD_ZERO, &ignored); offset +=3D bytes; } @@ -1180,6 +1225,7 @@ immediate_exit: assert(s->in_flight =3D=3D 0); qemu_vfree(s->buf); g_free(s->cow_bitmap); + g_free(s->zero_bitmap); g_free(s->in_flight_bitmap); bdrv_dirty_iter_free(s->dbi); @@ -1359,6 +1405,7 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMetho= d method, int ret; size_t qiov_offset =3D 0; int64_t dirty_bitmap_offset, dirty_bitmap_end; + int64_t zero_bitmap_offset, zero_bitmap_end; if (!QEMU_IS_ALIGNED(offset, job->granularity) && bdrv_dirty_bitmap_get(job->dirty_bitmap, offset)) @@ -1402,8 +1449,9 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMetho= d method, } /* - * Tails are either clean or shrunk, so for bitmap resetting - * we safely align the range down. + * Tails are either clean or shrunk, so for dirty bitmap resetting + * we safely align the range narrower. But for zero bitmap, round + * range wider for checking or clearing, and narrower for setting. */ dirty_bitmap_offset =3D QEMU_ALIGN_UP(offset, job->granularity); dirty_bitmap_end =3D QEMU_ALIGN_DOWN(offset + bytes, job->granularity); @@ -1411,22 +1459,44 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMet= hod method, bdrv_reset_dirty_bitmap(job->dirty_bitmap, dirty_bitmap_offset, dirty_bitmap_end - dirty_bitmap_offset); } + zero_bitmap_offset =3D offset / job->granularity; + zero_bitmap_end =3D DIV_ROUND_UP(offset + bytes, job->granularity); job_progress_increase_remaining(&job->common.job, bytes); job->active_write_bytes_in_flight +=3D bytes; switch (method) { case MIRROR_METHOD_COPY: + if (job->zero_bitmap) { + bitmap_clear(job->zero_bitmap, zero_bitmap_offset, + zero_bitmap_end - zero_bitmap_offset); + } ret =3D blk_co_pwritev_part(job->target, offset, bytes, qiov, qiov_offset, flags); break; case MIRROR_METHOD_ZERO: + if (job->zero_bitmap) { + if (find_next_zero_bit(job->zero_bitmap, zero_bitmap_end, + zero_bitmap_offset) =3D=3D zero_bitmap_= end) { + ret =3D 0; + break; + } + } assert(!qiov); ret =3D blk_co_pwrite_zeroes(job->target, offset, bytes, flags); + if (job->zero_bitmap && ret >=3D 0) { + bitmap_set(job->zero_bitmap, dirty_bitmap_offset / job->granul= arity, + (dirty_bitmap_end - dirty_bitmap_offset) / + job->granularity); + } break; case MIRROR_METHOD_DISCARD: + if (job->zero_bitmap) { + bitmap_clear(job->zero_bitmap, zero_bitmap_offset, + zero_bitmap_end - zero_bitmap_offset); + } assert(!qiov); ret =3D blk_co_pdiscard(job->target, offset, bytes); break; --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542583; cv=none; d=zohomail.com; s=zohoarc; b=mHIuBYE8FBTbk+7YmuCWxhMJOulmH3AW0UuKg/dovedmqXR0H/zGVkQRfnG0SadawuqfsWPoL2uw23ZjiIKmADG9+uBBsB5klpgyy4ZnxSadjRnYwuNULYzLEB55r+1eNHNo1rlgxX+562U5/2mZB7/CY5j2LoItNCTvyNlZwPY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542583; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=i16aZxxw0o1rdljUx+f96coAB3U70GB6E7l1CM3DuE8=; b=hKkMRD3ajKuKOp7qJqHhzntQLlqGu0PrMXkSJR1psIklcAvXCUnWNipnScJJDkWyMiz2gubeIhfxs50HSuuaoK/QVok9Mryg9pwcB+0n+iV8pByY/kojf8EiQaiwQzi++OLp2zUhDCFrP/UJk4Z+JCXxKlhtoFd2qiMlNWCGka4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542583798296.5769242123441; Thu, 24 Apr 2025 17:56:23 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87Ll-00070T-6D; Thu, 24 Apr 2025 20:55:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87Lh-0006zV-Kb for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:25 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87Lf-0000nh-8J for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:25 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-35-tEibCA-cPOWMISF5UEgsXA-1; Thu, 24 Apr 2025 20:55:18 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 92C3C1800446; Fri, 25 Apr 2025 00:55:16 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 472F61800374; Fri, 25 Apr 2025 00:55:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542522; 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=i16aZxxw0o1rdljUx+f96coAB3U70GB6E7l1CM3DuE8=; b=ALJ7fQLh8JowBA1ed9fM3zD4hEyF8pp7J9SZ+hh3Z+neIJDP4usdXZe7FzfAS9hPT4ffYA GsFL97V8FBwF5DuN9w6YJJPZbyzkoZC+sO4MR8V/ezxounxAcG8WePR9K4F9nfxS/BnFiC PJJf5wOFHLv9RbBbds1a+9ZHn9mLHAU= X-MC-Unique: tEibCA-cPOWMISF5UEgsXA-1 X-Mimecast-MFC-AGG-ID: tEibCA-cPOWMISF5UEgsXA_1745542516 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Andrey Drobyshev , Alexander Ivanov , Alberto Garcia , Kevin Wolf , Hanna Reitz Subject: [PATCH v3 09/11] iotests/common.rc: add disk_usage function Date: Thu, 24 Apr 2025 19:52:09 -0500 Message-ID: <20250425005439.2252467-22-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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.129.124; envelope-from=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542584740019000 Content-Type: text/plain; charset="utf-8" From: Andrey Drobyshev Move the definition from iotests/250 to common.rc. This is used to detect real disk usage of sparse files. In particular, we want to use it for checking subclusters-based discards. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov Reviewed-by: Alberto Garcia Message-ID: <20240913163942.423050-6-andrey.drobyshev@virtuozzo.com> Signed-off-by: Eric Blake Reviewed-by: Stefan Hajnoczi --- tests/qemu-iotests/common.rc | 6 ++++++ tests/qemu-iotests/250 | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 95c12577dd4..237f746af88 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -140,6 +140,12 @@ _optstr_add() fi } +# report real disk usage for sparse files +disk_usage() +{ + du --block-size=3D1 "$1" | awk '{print $1}' +} + # Set the variables to the empty string to turn Valgrind off # for specific processes, e.g. # $ VALGRIND_QEMU_IO=3D ./check -qcow2 -valgrind 015 diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250 index af48f83abac..c0a0dbc0ff1 100755 --- a/tests/qemu-iotests/250 +++ b/tests/qemu-iotests/250 @@ -52,11 +52,6 @@ _unsupported_imgopts data_file # bdrv_co_truncate(bs->file) call in qcow2_co_truncate(), which might succ= eed # anyway. -disk_usage() -{ - du --block-size=3D1 $1 | awk '{print $1}' -} - size=3D2100M _make_test_img -o "cluster_size=3D1M,preallocation=3Dmetadata" $size --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542569; cv=none; d=zohomail.com; s=zohoarc; b=FDpfET/7fJRKgqJa643EPIHZESx8U9RtJZKwDC9K//nFyH6RNovhblyhHy4QiZMAXSB4Ysw+RbdViluKnAlNvn1Uk5uMK/kYUT2w/64PsctbcR/kRPOnRQBXfXVn+Tqj6Lt7LNmfixt2cRsYUw7Vj5RrDOYNBQf4Q8L5lmKnun4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542569; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=NRLd7boJqvVSVN51xZPvCh0dSNAo4MXyysFZo2lzQio=; b=bZp3YvhcW4xDHTdObt7tX7QJtpQVZTuTR8MBgikm0MbOrcFAWcdYX/4TqAPiMaHKuYt9G11+uNZXs/YIheMhdctTWezjHWMGtonHhyfBlx7qhVRz5gKGHy0/lyE/KtAUWzobJyBrsDoJ1uIHg+umdgf50ygVWegk2v7NfOCfwHE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542569451860.9689691267514; Thu, 24 Apr 2025 17:56:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87Lo-00070u-2W; Thu, 24 Apr 2025 20:55:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87Lh-0006zc-Vh for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:26 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87Le-0000nY-Kd for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:25 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-12-K94r-eUSPFSJQkfkcq1CFg-1; Thu, 24 Apr 2025 20:55:19 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CF4E21956089; Fri, 25 Apr 2025 00:55:18 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 042CE1800378; Fri, 25 Apr 2025 00:55:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542522; 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=NRLd7boJqvVSVN51xZPvCh0dSNAo4MXyysFZo2lzQio=; b=izmQf+0y39bwY6HEx2lE5R1D/g1h18uysNRczSTnbi/EIeV3WLXMMTZMYJrPJGtkWXK4/u 0Do7yGeyLWhC01o4phM/GDGwlkndnCI897wSucEY0TVXGZ/27Llsd4EdaM4OgaXyVAdVEN Lskb3wyo0WmLXp1M75+inhQ0CWlaxE8= X-MC-Unique: K94r-eUSPFSJQkfkcq1CFg-1 X-Mimecast-MFC-AGG-ID: K94r-eUSPFSJQkfkcq1CFg_1745542518 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Kevin Wolf , Hanna Reitz Subject: [PATCH v3 10/11] tests: Add iotest mirror-sparse for recent patches Date: Thu, 24 Apr 2025 19:52:10 -0500 Message-ID: <20250425005439.2252467-23-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542570676019000 Content-Type: text/plain; charset="utf-8" Prove that blockdev-mirror can now result in sparse raw destination files, regardless of whether the source is raw or qcow2. By making this a separate test, it was possible to test effects of individual patches for the various pieces that all have to work together for a sparse mirror to be successful. Note that ./check -file produces different job lengths than ./check -qcow2 (the test uses a filter to normalize); that's because when deciding how much of the image to be mirrored, the code looks at how much of the source image was allocated (for qcow2, this is only the written clusters; for raw, it is the entire file). But the important part is that the destination file ends up smaller than 3M, rather than the 20M it used to be before this patch series. Signed-off-by: Eric Blake --- Improve test with more cases --- tests/qemu-iotests/tests/mirror-sparse | 128 ++++++++ tests/qemu-iotests/tests/mirror-sparse.out | 365 +++++++++++++++++++++ 2 files changed, 493 insertions(+) create mode 100755 tests/qemu-iotests/tests/mirror-sparse create mode 100644 tests/qemu-iotests/tests/mirror-sparse.out diff --git a/tests/qemu-iotests/tests/mirror-sparse b/tests/qemu-iotests/te= sts/mirror-sparse new file mode 100755 index 00000000000..33cc7a1e5f3 --- /dev/null +++ b/tests/qemu-iotests/tests/mirror-sparse @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# group: rw auto quick +# +# Test blockdev-mirror with raw sparse destination +# +# Copyright (C) 2025 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +seq=3D"$(basename $0)" +echo "QA output created by $seq" + +status=3D1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + _cleanup_qemu +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +cd .. +. ./common.rc +. ./common.filter +. ./common.qemu + +_supported_fmt qcow2 raw # Format of the source. dst is always raw file +_supported_proto file +_supported_os Linux + +filter_len() { + sed -e 's/"len": [0-9]*/"len": LEN/g' \ + -e 's/"offset": [0-9]*/"offset": OFFSET/g' +} + +echo +echo "=3D=3D=3D Initial image setup =3D=3D=3D" +echo + +TEST_IMG=3D"$TEST_IMG.base" _make_test_img 20M +$QEMU_IO -c 'w 8M 2M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io + +_launch_qemu -machine q35 \ + -blockdev '{"driver":"file", "cache":{"direct":true, "no-flush":false}, + "filename":"'"$TEST_IMG.base"'", "node-name":"src-file"}' \ + -blockdev '{"driver":"'$IMGFMT'", "node-name":"src", "file":"src-file"= }' +h1=3D$QEMU_HANDLE +_send_qemu_cmd $h1 '{"execute": "qmp_capabilities"}' 'return' + +# Check several combinations; most should result in a sparse destination; +# the destination should only be fully allocated if pre-allocated +# and not punching holes due to detect-zeroes +# do_test creation discard zeroes result +do_test() { + creation=3D$1 + discard=3D$2 + zeroes=3D$3 + expected=3D$4 + +echo +echo "=3D=3D=3D Testing creation=3D$creation discard=3D$discard zeroes=3D$= zeroes =3D=3D=3D" +echo + +rm -f $TEST_IMG +if test $creation =3D external; then + truncate --size=3D20M $TEST_IMG +else + _send_qemu_cmd $h1 '{"execute": "blockdev-create", "arguments": + {"options": {"driver":"file", "filename":"'$TEST_IMG'", + "size":'$((20*1024*1024))', "preallocation":"'$creation'"}, + "job-id":"job1"}}' 'concluded' + _send_qemu_cmd $h1 '{"execute": "job-dismiss", "arguments": + {"id": "job1"}}' 'return' +fi +_send_qemu_cmd $h1 '{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"'$TEST_IMG'", "aio":"threads", + "auto-read-only":true, "discard":"'$discard'", + "detect-zeroes":"'$zeroes'"}}' 'return' +_send_qemu_cmd $h1 '{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}}' 'return' +_timed_wait_for $h1 '"ready"' +_send_qemu_cmd $h1 '{"execute": "job-complete", "arguments": + {"id":"job2"}}' 'return' | filter_len +_send_qemu_cmd $h1 '{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}}' 'return' | filter_len +$QEMU_IMG compare -U -f $IMGFMT -F raw $TEST_IMG.base $TEST_IMG +result=3D$(disk_usage $TEST_IMG) +if test $result -lt $((3*1024*1024)); then + actual=3Dsparse +elif test $result =3D $((20*1024*1024)); then + actual=3Dfull +else + actual=3Dunknown +fi +echo "Destination is $actual; expected $expected" +} + +do_test external ignore off sparse +do_test external unmap off sparse +do_test external unmap unmap sparse +do_test off ignore off sparse +do_test off unmap off sparse +do_test off unmap unmap sparse +do_test full ignore off full +do_test full unmap off sparse +do_test full unmap unmap sparse + +_send_qemu_cmd $h1 '{"execute":"quit"}' '' + +# success, all done +echo '*** done' +rm -f $seq.full +status=3D0 diff --git a/tests/qemu-iotests/tests/mirror-sparse.out b/tests/qemu-iotest= s/tests/mirror-sparse.out new file mode 100644 index 00000000000..2103b891c3f --- /dev/null +++ b/tests/qemu-iotests/tests/mirror-sparse.out @@ -0,0 +1,365 @@ +QA output created by mirror-sparse + +=3D=3D=3D Initial image setup =3D=3D=3D + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=3DIMGFMT size=3D20971520 +wrote 2097152/2097152 bytes at offset 8388608 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"execute": "qmp_capabilities"} +{"return": {}} + +=3D=3D=3D Testing creation=3Dexternal discard=3Dignore zeroes=3Doff =3D=3D= =3D + +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"ignore", + "detect-zeroes":"off"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse + +=3D=3D=3D Testing creation=3Dexternal discard=3Dunmap zeroes=3Doff =3D=3D= =3D + +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"unmap", + "detect-zeroes":"off"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse + +=3D=3D=3D Testing creation=3Dexternal discard=3Dunmap zeroes=3Dunmap =3D= =3D=3D + +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"unmap", + "detect-zeroes":"unmap"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse + +=3D=3D=3D Testing creation=3Doff discard=3Dignore zeroes=3Doff =3D=3D=3D + +{"execute": "blockdev-create", "arguments": + {"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT", + "size":20971520, "preallocation":"off"}, + "job-id":"job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}} +{"execute": "job-dismiss", "arguments": + {"id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"ignore", + "detect-zeroes":"off"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse + +=3D=3D=3D Testing creation=3Doff discard=3Dunmap zeroes=3Doff =3D=3D=3D + +{"execute": "blockdev-create", "arguments": + {"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT", + "size":20971520, "preallocation":"off"}, + "job-id":"job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}} +{"execute": "job-dismiss", "arguments": + {"id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"unmap", + "detect-zeroes":"off"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse + +=3D=3D=3D Testing creation=3Doff discard=3Dunmap zeroes=3Dunmap =3D=3D=3D + +{"execute": "blockdev-create", "arguments": + {"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT", + "size":20971520, "preallocation":"off"}, + "job-id":"job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}} +{"execute": "job-dismiss", "arguments": + {"id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"unmap", + "detect-zeroes":"unmap"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse + +=3D=3D=3D Testing creation=3Dfull discard=3Dignore zeroes=3Doff =3D=3D=3D + +{"execute": "blockdev-create", "arguments": + {"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT", + "size":20971520, "preallocation":"full"}, + "job-id":"job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}} +{"execute": "job-dismiss", "arguments": + {"id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"ignore", + "detect-zeroes":"off"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is full; expected full + +=3D=3D=3D Testing creation=3Dfull discard=3Dunmap zeroes=3Doff =3D=3D=3D + +{"execute": "blockdev-create", "arguments": + {"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT", + "size":20971520, "preallocation":"full"}, + "job-id":"job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}} +{"execute": "job-dismiss", "arguments": + {"id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"unmap", + "detect-zeroes":"off"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse + +=3D=3D=3D Testing creation=3Dfull discard=3Dunmap zeroes=3Dunmap =3D=3D=3D + +{"execute": "blockdev-create", "arguments": + {"options": {"driver":"file", "filename":"TEST_DIR/t.IMGFMT", + "size":20971520, "preallocation":"full"}, + "job-id":"job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job1"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job1"}} +{"execute": "job-dismiss", "arguments": + {"id": "job1"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job1"}} +{"return": {}} +{"execute": "blockdev-add", "arguments": + {"node-name": "dst", "driver":"file", + "filename":"TEST_DIR/t.IMGFMT", "aio":"threads", + "auto-read-only":true, "discard":"unmap", + "detect-zeroes":"unmap"}} +{"return": {}} +{"execute":"blockdev-mirror", "arguments": + {"sync":"full", "device":"src", "target":"dst", + "job-id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job2"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job2"}} +{"execute": "job-complete", "arguments": + {"id":"job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_READY", "data": {"device": "job2", "len": LEN, "offset": OFFSE= T, "speed": 0, "type": "mirror"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": + {"node-name": "dst"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_JOB_COMPLETED", "data": {"device": "job2", "len": LEN, "offset": O= FFSET, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job2"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job2"}} +{"return": {}} +Images are identical. +Destination is sparse; expected sparse +{"execute":"quit"} +*** done --=20 2.49.0 From nobody Sun Oct 5 13:57:41 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1745542646; cv=none; d=zohomail.com; s=zohoarc; b=Z0AH4ax8HmA/EQCZOAfo7cdTWIOENge8SqidCeseGowJnTTX0FT23EcCaB+JjvavAq+Gus/G9mx18XOHa/XGMLCCqYrA9H5hi6qGq7lA/WydYkVdtXNEnAgL3hRXEB1B993XwhhNj9TaE7JO+GSaADEFNo258FtvzkvtSKLWK9s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1745542646; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=4wAKS4SfzEqvGnIXI4PNlsxK1Beih4ozBtm96dyoYU4=; b=idLBeAaabMBeSUysjXZv5UPi5oMN+U0qH9IT5rh5uBaZJR6XyOFXtt0jP8PT8SrhMenIjFbjYsDUVy9dvFRCuC7rVDZv16GyPe8f/tiUls1Xh9nMiklUXgld127fWPd6auHcnV5yIDgcDggXuYj/z8UqFoAlzHqa6TBU40sUeQY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1745542646775499.10621771092667; Thu, 24 Apr 2025 17:57:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u87MV-0007hj-5Z; Thu, 24 Apr 2025 20:56:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87Ll-00070c-Lu for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:30 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u87Lj-0000oP-T1 for qemu-devel@nongnu.org; Thu, 24 Apr 2025 20:55:29 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-640-TQbrQqJ6PPaX_w6YMH_ybw-1; Thu, 24 Apr 2025 20:55:22 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 802F71800264; Fri, 25 Apr 2025 00:55:21 +0000 (UTC) Received: from green.redhat.com (unknown [10.2.16.59]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 270A31800374; Fri, 25 Apr 2025 00:55:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1745542526; 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=4wAKS4SfzEqvGnIXI4PNlsxK1Beih4ozBtm96dyoYU4=; b=biWMj62Rz12AGX/5Syy0SJynpjMDJ2RBsxDK9RnY4dMLMup+nuqgFID5IUa7cFwMK2cViG pvbQeGu8H90dXLeCqmehv3+I7SG5ajUo6gjL08dYfpX8/ZZhwiNR80lCygn4xUEbbBXeOp rujOF2Rs3bVAq2hYgaRYbxdIsDl1HEw= X-MC-Unique: TQbrQqJ6PPaX_w6YMH_ybw-1 X-Mimecast-MFC-AGG-ID: TQbrQqJ6PPaX_w6YMH_ybw_1745542521 From: Eric Blake To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, vsementsov@yandex-team.ru, stefanha@redhat.com, Markus Armbruster , John Snow , Kevin Wolf , Hanna Reitz Subject: [PATCH v3 11/11] mirror: Allow QMP override to declare target already zero Date: Thu, 24 Apr 2025 19:52:11 -0500 Message-ID: <20250425005439.2252467-24-eblake@redhat.com> In-Reply-To: <20250425005439.2252467-13-eblake@redhat.com> References: <20250425005439.2252467-13-eblake@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=eblake@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.84, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1745542649169019100 Content-Type: text/plain; charset="utf-8" QEMU's attempts to learn whether a destination file starts life with all zero contents are just a heuristic. There may be cases where the caller is aware of information that QEMU cannot learn quickly, in which case telling QEMU what to assume about the destination can make the mirror operation faster. Given our existing example of "qemu-img convert --target-is-zero", it is time to expose this override in QMP for blockdev-mirror as well. Signed-off-by: Eric Blake Acked-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi --- qapi/block-core.json | 8 +++++++- include/block/block_int-global-state.h | 3 ++- block/mirror.c | 23 +++++++++++++++-------- blockdev.c | 18 +++++++++++------- tests/unit/test-block-iothread.c | 2 +- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index b1937780e19..7f70ec6d3cb 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2538,6 +2538,11 @@ # disappear from the query list without user intervention. # Defaults to true. (Since 3.1) # +# @target-is-zero: Assume the destination reads as all zeroes before +# the mirror started. Setting this to true can speed up the +# mirror. Setting this to true when the destination is not +# actually all zero can corrupt the destination. (Since 10.1) +# # Since: 2.6 # # .. qmp-example:: @@ -2557,7 +2562,8 @@ '*on-target-error': 'BlockdevOnError', '*filter-node-name': 'str', '*copy-mode': 'MirrorCopyMode', - '*auto-finalize': 'bool', '*auto-dismiss': 'bool' }, + '*auto-finalize': 'bool', '*auto-dismiss': 'bool', + '*target-is-zero': 'bool'}, 'allow-preconfig': true } ## diff --git a/include/block/block_int-global-state.h b/include/block/block_i= nt-global-state.h index eb2d92a2261..a2b96f90d44 100644 --- a/include/block/block_int-global-state.h +++ b/include/block/block_int-global-state.h @@ -140,6 +140,7 @@ BlockJob *commit_active_start(const char *job_id, Block= DriverState *bs, * @mode: Whether to collapse all images in the chain to the target. * @backing_mode: How to establish the target's backing chain after comple= tion. * @zero_target: Whether the target should be explicitly zero-initialized + * @target_is_zero: Whether the target already is zero-initialized * @on_source_error: The action to take upon error reading from the source. * @on_target_error: The action to take upon error writing to the target. * @unmap: Whether to unmap target where source sectors only contain zeroe= s. @@ -159,7 +160,7 @@ void mirror_start(const char *job_id, BlockDriverState = *bs, int creation_flags, int64_t speed, uint32_t granularity, int64_t buf_size, MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, - bool zero_target, + bool zero_target, bool target_is_zero, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, const char *filter_node_name, diff --git a/block/mirror.c b/block/mirror.c index 69a02dfc2b7..69467db0f79 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -55,6 +55,8 @@ typedef struct MirrorBlockJob { BlockMirrorBackingMode backing_mode; /* Whether the target image requires explicit zero-initialization */ bool zero_target; + /* Whether the target should be assumed to be already zero initialized= */ + bool target_is_zero; /* * To be accesssed with atomics. Written only under the BQL (required = by the * current implementation of mirror_change()). @@ -892,9 +894,13 @@ static int coroutine_fn GRAPH_UNLOCKED mirror_dirty_in= it(MirrorBlockJob *s) int64_t bitmap_length =3D DIV_ROUND_UP(s->bdev_length, s->granular= ity); offset =3D 0; - bdrv_graph_co_rdlock(); - ret =3D bdrv_co_is_all_zeroes(target_bs); - bdrv_graph_co_rdunlock(); + if (s->target_is_zero) { + ret =3D 1; + } else { + bdrv_graph_co_rdlock(); + ret =3D bdrv_co_is_all_zeroes(target_bs); + bdrv_graph_co_rdunlock(); + } if (ret < 0) { return ret; } @@ -1799,7 +1805,7 @@ static BlockJob *mirror_start_job( const char *replaces, int64_t speed, uint32_t granularity, int64_t buf_size, BlockMirrorBackingMode backing_mode, - bool zero_target, + bool zero_target, bool target_is_zero, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, @@ -1968,6 +1974,7 @@ static BlockJob *mirror_start_job( s->is_none_mode =3D is_none_mode; s->backing_mode =3D backing_mode; s->zero_target =3D zero_target; + s->target_is_zero =3D target_is_zero; qatomic_set(&s->copy_mode, copy_mode); s->base =3D base; s->base_overlay =3D bdrv_find_overlay(bs, base); @@ -2096,7 +2103,7 @@ void mirror_start(const char *job_id, BlockDriverStat= e *bs, int creation_flags, int64_t speed, uint32_t granularity, int64_t buf_size, MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, - bool zero_target, + bool zero_target, bool target_is_zero, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, const char *filter_node_name, @@ -2121,8 +2128,8 @@ void mirror_start(const char *job_id, BlockDriverStat= e *bs, mirror_start_job(job_id, bs, creation_flags, target, replaces, speed, granularity, buf_size, backing_mode, zero_targ= et, - on_source_error, on_target_error, unmap, NULL, NULL, - &mirror_job_driver, is_none_mode, base, false, + target_is_zero, on_source_error, on_target_error, unm= ap, + NULL, NULL, &mirror_job_driver, is_none_mode, base, f= alse, filter_node_name, true, copy_mode, false, errp); } @@ -2148,7 +2155,7 @@ BlockJob *commit_active_start(const char *job_id, Blo= ckDriverState *bs, job =3D mirror_start_job( job_id, bs, creation_flags, base, NULL, speed, 0, 0, - MIRROR_LEAVE_BACKING_CHAIN, false, + MIRROR_LEAVE_BACKING_CHAIN, false, false, on_error, on_error, true, cb, opaque, &commit_active_job_driver, false, base, auto_complete, filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND, diff --git a/blockdev.c b/blockdev.c index 1d1f27cfff6..6f5373991c8 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2798,7 +2798,7 @@ static void blockdev_mirror_common(const char *job_id= , BlockDriverState *bs, const char *replaces, enum MirrorSyncMode sync, BlockMirrorBackingMode backing_mode, - bool zero_target, + bool zero_target, bool target_is_zero, bool has_speed, int64_t speed, bool has_granularity, uint32_t granular= ity, bool has_buf_size, int64_t buf_size, @@ -2909,11 +2909,10 @@ static void blockdev_mirror_common(const char *job_= id, BlockDriverState *bs, /* pass the node name to replace to mirror start since it's loose coup= ling * and will allow to check whether the node still exist at mirror comp= letion */ - mirror_start(job_id, bs, target, - replaces, job_flags, + mirror_start(job_id, bs, target, replaces, job_flags, speed, granularity, buf_size, sync, backing_mode, zero_ta= rget, - on_source_error, on_target_error, unmap, filter_node_name, - copy_mode, errp); + target_is_zero, on_source_error, on_target_error, unmap, + filter_node_name, copy_mode, errp); } void qmp_drive_mirror(DriveMirror *arg, Error **errp) @@ -2928,6 +2927,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) int64_t size; const char *format =3D arg->format; bool zero_target; + bool target_is_zero; int ret; bs =3D qmp_get_root_bs(arg->device, errp); @@ -3044,6 +3044,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) zero_target =3D (arg->sync =3D=3D MIRROR_SYNC_MODE_FULL && (arg->mode =3D=3D NEW_IMAGE_MODE_EXISTING || !bdrv_has_zero_init(target_bs))); + target_is_zero =3D (arg->mode =3D=3D NEW_IMAGE_MODE_ABSOLUTE_PATHS && + bdrv_has_zero_init(target_bs)); bdrv_graph_rdunlock_main_loop(); @@ -3055,7 +3057,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) blockdev_mirror_common(arg->job_id, bs, target_bs, arg->replaces, arg->sync, - backing_mode, zero_target, + backing_mode, zero_target, target_is_zero, arg->has_speed, arg->speed, arg->has_granularity, arg->granularity, arg->has_buf_size, arg->buf_size, @@ -3085,6 +3087,7 @@ void qmp_blockdev_mirror(const char *job_id, bool has_copy_mode, MirrorCopyMode copy_mode, bool has_auto_finalize, bool auto_finalize, bool has_auto_dismiss, bool auto_dismiss, + bool has_target_is_zero, bool target_is_zero, Error **errp) { BlockDriverState *bs; @@ -3115,7 +3118,8 @@ void qmp_blockdev_mirror(const char *job_id, blockdev_mirror_common(job_id, bs, target_bs, replaces, sync, backing_mode, - zero_target, has_speed, speed, + zero_target, has_target_is_zero && target_is_ze= ro, + has_speed, speed, has_granularity, granularity, has_buf_size, buf_size, has_on_source_error, on_source_error, diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothr= ead.c index e26b3be5939..54aed8252c0 100644 --- a/tests/unit/test-block-iothread.c +++ b/tests/unit/test-block-iothread.c @@ -755,7 +755,7 @@ static void test_propagate_mirror(void) /* Start a mirror job */ mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0, - MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false, + MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false, = false, BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT, false, "filter_node", MIRROR_COPY_MODE_BACKGROUND, &error_abort); --=20 2.49.0