From patchwork Fri Sep 13 16:39:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803836 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 68CC4FC6166 for ; Fri, 13 Sep 2024 16:41:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Ks-0006H6-L7; Fri, 13 Sep 2024 12:39:54 -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 1sp9Kn-00064N-Sd; Fri, 13 Sep 2024 12:39:50 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000qC-6v; Fri, 13 Sep 2024 12:39:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=g/TdJ5qXyf+1Rtq7JvfFokbbeo/irttxDxGcy32Lx1Y=; b=NEfuouYZGS0h GBEenzfZW6KJCwxQX3fDjOGCOycF8SaVsq3Vxyir909D9y/SlfpSDxPMphvP6Fmelesub7QKx53JB iCt+ie3NEdKyNZhxY3RhMAGT7CsSpami9TS6GNn7ATZZ6V1d2arOMdYhg8Ayk7fJefhrlRV9EGpwL tjYtEZpQ4xnnDF3BfkNVLM7J6KJa8ABEj+NvQFJqINy89CP1/xoUiG9EThsmokDZwqblg08mNXYxI /tkpq0LqAdcDar0TA1ricFsqQOv3HfUTVEDUKoLSPR+Ls18xXIDNOJJNTcxvDXT+a+CO8QKIVe0Pr Kn1jgfMiRa/KqS4Wmgtq2w==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-2R; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 01/12] qcow2: make function update_refcount_discard() global Date: Fri, 13 Sep 2024 19:39:31 +0300 Message-Id: <20240913163942.423050-2-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org We are going to need it for discarding separate subclusters. The function itself doesn't do anything with the refcount tables, it simply adds a discard request to the queue, so rename it to qcow2_queue_discard(). Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov Reviewed-by: Hanna Czenczek Reviewed-by: Alberto Garcia --- block/qcow2-refcount.c | 8 ++++---- block/qcow2.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 0266542cee..2026f5fa21 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -754,8 +754,8 @@ void qcow2_process_discards(BlockDriverState *bs, int ret) } } -static void update_refcount_discard(BlockDriverState *bs, - uint64_t offset, uint64_t length) +void qcow2_queue_discard(BlockDriverState *bs, uint64_t offset, + uint64_t length) { BDRVQcow2State *s = bs->opaque; Qcow2DiscardRegion *d, *p, *next; @@ -902,7 +902,7 @@ update_refcount(BlockDriverState *bs, int64_t offset, int64_t length, } if (s->discard_passthrough[type]) { - update_refcount_discard(bs, cluster_offset, s->cluster_size); + qcow2_queue_discard(bs, cluster_offset, s->cluster_size); } } } @@ -3619,7 +3619,7 @@ qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs) /* discard refblock from the cache if refblock is cached */ qcow2_cache_discard(s->refcount_block_cache, refblock); } - update_refcount_discard(bs, discard_block_offs, s->cluster_size); + qcow2_queue_discard(bs, discard_block_offs, s->cluster_size); return 0; } diff --git a/block/qcow2.h b/block/qcow2.h index a9e3481c6e..197bdcdf53 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -891,6 +891,8 @@ int coroutine_fn qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *re BdrvCheckMode fix); void GRAPH_RDLOCK qcow2_process_discards(BlockDriverState *bs, int ret); +void qcow2_queue_discard(BlockDriverState *bs, uint64_t offset, + uint64_t length); int GRAPH_RDLOCK qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, From patchwork Fri Sep 13 16:39:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803827 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D65D9FC6167 for ; Fri, 13 Sep 2024 16:40:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Kr-0006EL-TH; Fri, 13 Sep 2024 12:39:53 -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 1sp9Kn-00064M-T6; Fri, 13 Sep 2024 12:39:51 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000q8-6E; Fri, 13 Sep 2024 12:39:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=OeSkIH7knxZGHTt1LuTnXJidyr81oxLIC/BUMuLQL9k=; b=WQ76q1awnvy0 hJXg5JvCJkLTIfgdT/YLPuixz5rxT2HL5fpeQUyHLGUCQoZtxruReFqs9SezuuRklVoHbyjyfk7ep eDhyrtIFGffNvQWgPDA/jKwPojI9lySKt8qf9qPM5T7xq8VuUcrdG61CiGqlR0UOCByYhizaqWtka /7a3foqqZYGRtvLO9B/z1rQSl4InCmC29edVDqODKAy+CMSpZo3FbqVG62qmURO9OoCLq9X7/BPoX dYWkqX6f40AekujhQbbLuuXGJVDk18xSQmv+pRSUOlXqAHOEaGdnvgrOe2Yg5lIClFpLBDK/1TDq9 qU1+q7nvmEME3DvAuTjnpg==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-2c; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 02/12] qcow2: simplify L2 entries accounting for discard-no-unref Date: Fri, 13 Sep 2024 19:39:32 +0300 Message-Id: <20240913163942.423050-3-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Commits 42a2890a and b2b10904 introduce handling of discard-no-unref option in discard_in_l2_slice() and zero_in_l2_slice(). They add even more if's when chosing the right l2 entry. What we really need for this option is the new entry simply to contain the same host cluster offset, no matter whether we unmap or zeroize the cluster. For that OR'ing with the old entry is enough. This patch doesn't change the logic and is pure refactoring. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov Reviewed-by: Alberto Garcia --- block/qcow2-cluster.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index ce8c0076b3..5f057ba2fd 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1946,25 +1946,21 @@ discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters, new_l2_entry = new_l2_bitmap = 0; } else if (bs->backing || qcow2_cluster_is_allocated(cluster_type)) { if (has_subclusters(s)) { - if (keep_reference) { - new_l2_entry = old_l2_entry; - } else { - new_l2_entry = 0; - } + new_l2_entry = 0; new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES; } else { - if (s->qcow_version >= 3) { - if (keep_reference) { - new_l2_entry |= QCOW_OFLAG_ZERO; - } else { - new_l2_entry = QCOW_OFLAG_ZERO; - } - } else { - new_l2_entry = 0; - } + new_l2_entry = s->qcow_version >= 3 ? QCOW_OFLAG_ZERO : 0; } } + /* + * No need to check for the QCOW version since discard-no-unref is + * only allowed since version 3. + */ + if (keep_reference) { + new_l2_entry |= old_l2_entry; + } + if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) { continue; } @@ -2064,19 +2060,19 @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, ((flags & BDRV_REQ_MAY_UNMAP) && qcow2_cluster_is_allocated(type)); bool keep_reference = (s->discard_no_unref && type != QCOW2_CLUSTER_COMPRESSED); - uint64_t new_l2_entry = old_l2_entry; + uint64_t new_l2_entry = unmap ? 0 : old_l2_entry; uint64_t new_l2_bitmap = old_l2_bitmap; - if (unmap && !keep_reference) { - new_l2_entry = 0; - } - if (has_subclusters(s)) { new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES; } else { new_l2_entry |= QCOW_OFLAG_ZERO; } + if (keep_reference) { + new_l2_entry |= old_l2_entry; + } + if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) { continue; } From patchwork Fri Sep 13 16:39:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803835 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A09A1FC6160 for ; Fri, 13 Sep 2024 16:41:25 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Ks-0006GI-Df; Fri, 13 Sep 2024 12:39:54 -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 1sp9Kq-000691-LU; Fri, 13 Sep 2024 12:39:52 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000qE-HG; Fri, 13 Sep 2024 12:39:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=zC4fCxWV/vMdGB/slP81g3/r2Jc6ZB1bGvRJ/IHPzDA=; b=sDjQp3LWKKez 1GzOqTAMzlEaLilX1mVFNDQTW1fwoqouBlqhDUyPlTUk7hf83LwYg4qFv/1EN6b+fPVgVnQ1LcYrm 4Cl+JcqtdDUG/BrQeCGtOkGSOzbkzREg2AL14A/sVxg1h68rCnbEDRZrSVzBQCkwnFXMEKbh5tLTe DmZkZMwtvqCqvHBdPW2/WHKilUOSF6Xvy1x1FotifT0RBRfyyP3iBVwfBiSjpD40NfPQ6BO0tAf3V z7Zt535yU47FqFAxp95F6I9xFqGMJYoVsx/IjBQJzJrN+oG7Ab5rUk9BshuKRL1lMh3DtYSWVTIE3 deUiw6CWUF4mJ3UKOiI8cA==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-2m; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 03/12] qcow2: put discard requests in the common queue when discard-no-unref enabled Date: Fri, 13 Sep 2024 19:39:33 +0300 Message-Id: <20240913163942.423050-4-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Normally discard requests are stored in the queue attached to BDRVQcow2State to be processed later at once. Currently discard-no-unref option handling causes these requests to be processed straight away. Let's fix that. Note that when doing regular discards qcow2_free_any_cluster() would check for the presence of external data files for us and redirect request to underlying data_file. Here we want to do the same but avoid refcount updates, thus we perform the same checks. Suggested-by: Hanna Czenczek Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov --- block/qcow2-cluster.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 5f057ba2fd..7dff0bd5a1 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1893,6 +1893,28 @@ again: return 0; } +/* + * Helper for adding a discard request to the queue without any refcount + * modifications. If external data file is used redirects the request to + * the corresponding BdrvChild. + */ +static inline void +discard_no_unref_any_file(BlockDriverState *bs, uint64_t offset, + uint64_t length, QCow2ClusterType ctype, + enum qcow2_discard_type dtype) +{ + BDRVQcow2State *s = bs->opaque; + + if (s->discard_passthrough[dtype] && + (ctype == QCOW2_CLUSTER_NORMAL || ctype == QCOW2_CLUSTER_ZERO_ALLOC)) { + if (has_data_file(bs)) { + bdrv_pdiscard(s->data_file, offset, length); + } else { + qcow2_queue_discard(bs, offset, length); + } + } +} + /* * This discards as many clusters of nb_clusters as possible at once (i.e. * all clusters in the same L2 slice) and returns the number of discarded @@ -1974,12 +1996,10 @@ discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters, if (!keep_reference) { /* Then decrease the refcount */ qcow2_free_any_cluster(bs, old_l2_entry, type); - } else if (s->discard_passthrough[type] && - (cluster_type == QCOW2_CLUSTER_NORMAL || - cluster_type == QCOW2_CLUSTER_ZERO_ALLOC)) { + } else { /* If we keep the reference, pass on the discard still */ - bdrv_pdiscard(s->data_file, old_l2_entry & L2E_OFFSET_MASK, - s->cluster_size); + discard_no_unref_any_file(bs, old_l2_entry & L2E_OFFSET_MASK, + s->cluster_size, cluster_type, type); } } @@ -2088,12 +2108,11 @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, if (!keep_reference) { /* Then decrease the refcount */ qcow2_free_any_cluster(bs, old_l2_entry, QCOW2_DISCARD_REQUEST); - } else if (s->discard_passthrough[QCOW2_DISCARD_REQUEST] && - (type == QCOW2_CLUSTER_NORMAL || - type == QCOW2_CLUSTER_ZERO_ALLOC)) { + } else { /* If we keep the reference, pass on the discard still */ - bdrv_pdiscard(s->data_file, old_l2_entry & L2E_OFFSET_MASK, - s->cluster_size); + discard_no_unref_any_file(bs, old_l2_entry & L2E_OFFSET_MASK, + s->cluster_size, type, + QCOW2_DISCARD_REQUEST); } } } From patchwork Fri Sep 13 16:39:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803838 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 85974FC6160 for ; Fri, 13 Sep 2024 16:42:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Kt-0006JA-5m; Fri, 13 Sep 2024 12:39:55 -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 1sp9Kp-00064c-2d; Fri, 13 Sep 2024 12:39:51 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000q5-72; Fri, 13 Sep 2024 12:39:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=ArUS/2lPV+fzhq7HB4Qvl1qp+hz9WlMqmNQIim6zw0I=; b=tN9g0vOZB7fa tXFZLoy9YMBCxHpeyV0hxh6zhO84GCY0rK/PEVPYN5gUJ10ThCG7wBGCWBhC2igUZo/UEyrCr44tq Q4e2e4RQB97kx8SkdU2PPiGjYtybTBCgRL0wfNTDG8ybc/VS4xLAK1iocRvydP/a+1+sEPfQnerCR 7hUFYPFhV98kRFTWOePQMXb2j44MAZrkBVXlqstEu1RZROvHj6P0pX8NFK5sNrGxPUUpHI65TPJFZ lzxbiXoZOT2F29hlsW7NQ09eh8zBTu0fTtiARxfXtDkREtkh5nZ4OKSyZKa0p1pWvS+FvF17Irmle Xj6cw2hOK1n7GdKa/T+rgA==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-2o; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 04/12] block/file-posix: add trace event for fallocate() calls Date: Fri, 13 Sep 2024 19:39:34 +0300 Message-Id: <20240913163942.423050-5-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This would ease debugging of write zeroes and discard operations. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov Reviewed-by: Alberto Garcia --- block/file-posix.c | 1 + block/trace-events | 1 + 2 files changed, 2 insertions(+) diff --git a/block/file-posix.c b/block/file-posix.c index ff928b5e85..9016057926 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1862,6 +1862,7 @@ static int translate_err(int err) static int do_fallocate(int fd, int mode, off_t offset, off_t len) { do { + trace_file_do_fallocate(fd, mode, offset, len); if (fallocate(fd, mode, offset, len) == 0) { return 0; } diff --git a/block/trace-events b/block/trace-events index 8e789e1f12..2f7ad28996 100644 --- a/block/trace-events +++ b/block/trace-events @@ -203,6 +203,7 @@ curl_setup_preadv(uint64_t bytes, uint64_t start, const char *range) "reading %" curl_close(void) "close" # file-posix.c +file_do_fallocate(int fd, int mode, int64_t offset, int64_t len) "fd=%d mode=0x%02x offset=%" PRIi64 " len=%" PRIi64 file_copy_file_range(void *bs, int src, int64_t src_off, int dst, int64_t dst_off, int64_t bytes, int flags, int64_t ret) "bs %p src_fd %d offset %"PRIu64" dst_fd %d offset %"PRIu64" bytes %"PRIu64" flags %d ret %"PRId64 file_FindEjectableOpticalMedia(const char *media) "Matching using %s" file_setup_cdrom(const char *partition) "Using %s as optical disc" From patchwork Fri Sep 13 16:39:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803839 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3D12DFC6160 for ; Fri, 13 Sep 2024 16:42:16 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Ku-0006Nd-89; Fri, 13 Sep 2024 12:39:56 -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 1sp9Kq-00069W-Pz; Fri, 13 Sep 2024 12:39:52 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000qD-9G; Fri, 13 Sep 2024 12:39:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=vEYGEDXABfP2ApaH+fC/vnkAPx15l1j90Jfj8gn89ys=; b=iyrExQZlIaCI rPNC2Y6YCdGOhjSAR00wvJ9CAWJ5fxM6LLqSbBlJ2P94NUg6WB0J4daBVVkVdP5sr5Rhec2GQEj5d IN0tGciZm3Q97nPBgy9SuBxXTklnkS3JXdPqEf0BASDYwxA8InADAGXl3cnxfCbwji73lZctjF9+U A/ubuLhF/wTgYEHUQ/CV+KqqZgcCtHrfroKilkOomkxzX+4InZLcmrA/R/dlfRttIbI+D7QugtRpM 5zWvA87/fIXB//4Hojmfmnw/nLGMix5y6VNq1fd5IVdJl7mhXgP9DBNWCVDjSbBT7Il5tEYvZTUrI 8lmsaa1I0umLqbosICIjqA==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-2q; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 05/12] iotests/common.rc: add disk_usage function Date: Fri, 13 Sep 2024 19:39:35 +0300 Message-Id: <20240913163942.423050-6-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org 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 --- tests/qemu-iotests/250 | 5 ----- tests/qemu-iotests/common.rc | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/qemu-iotests/250 b/tests/qemu-iotests/250 index af48f83aba..c0a0dbc0ff 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 succeed # anyway. -disk_usage() -{ - du --block-size=1 $1 | awk '{print $1}' -} - size=2100M _make_test_img -o "cluster_size=1M,preallocation=metadata" $size diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 95c12577dd..237f746af8 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=1 "$1" | awk '{print $1}' +} + # Set the variables to the empty string to turn Valgrind off # for specific processes, e.g. # $ VALGRIND_QEMU_IO= ./check -qcow2 -valgrind 015 From patchwork Fri Sep 13 16:39:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803837 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0220AFC6160 for ; Fri, 13 Sep 2024 16:41:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Kt-0006LI-Pv; Fri, 13 Sep 2024 12:39:55 -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 1sp9Kq-00069X-Pa; Fri, 13 Sep 2024 12:39:52 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000qA-8c; Fri, 13 Sep 2024 12:39:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=yXXklwEAMpNetDgLx0ch4zNLEZrZ08W+a1deIp7OFZg=; b=p1+Fx86UCj4r aCsjgh5Kuu9/ESvFDynp8PSryxzg7u0+kc51rwTOoRdYjAx1kP/XKgNpfUqeg+jwyuQIDYmrFPa5E kRqxI7FwOMLAMZvTWoXb8+vP/ICeSwHoIVod+/faOKF2q1dZRinzaNeO9+PXE/H4opeVCqt5fGdqM L19U78PqaKqML6qexQ7UPxpSRjmxSPE1ofex76Cm5SQncCnTk00xBMQqvnOd5EBZNczqYKpFyn+YW eVY2BJFKDTNgyamcnAfh0nI+mH69E/+CBxIMfNY9YuD1o2U8BdspwliM3uLKnd7DCqCaCcz2EtoOt FSUuW/jVL7kQ6DZCjlZvIQ==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-2s; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 06/12] iotests/290: add test case to check 'discard-no-unref' option behavior Date: Fri, 13 Sep 2024 19:39:36 +0300 Message-Id: <20240913163942.423050-7-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org We basically fill 2 images with identical data and perform discard operations with and without 'discard-no-unref' enabled. Then we check that images still read identically, that their disk usage is the same (i.e. fallocate(FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE) is called for both) and that with the option enabled cluster is still marked as allocated in "qemu-img map" output. We also check that the option doesn't work with qcow2 v2 images. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov Reviewed-by: Alberto Garcia --- tests/qemu-iotests/290 | 34 ++++++++++++++++++++++++++++++++++ tests/qemu-iotests/290.out | 28 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/tests/qemu-iotests/290 b/tests/qemu-iotests/290 index 776b59de1b..4eb929d15f 100755 --- a/tests/qemu-iotests/290 +++ b/tests/qemu-iotests/290 @@ -92,6 +92,40 @@ for qcow2_compat in 0.10 1.1; do $QEMU_IMG map "$TEST_IMG" | _filter_testdir done +echo +echo "### Test 'qemu-io -c discard' with 'discard-no-unref' option enabled" +echo + +echo "# Check that qcow2 v2 images don't support 'discard-no-unref' option" +NOUNREF_IMG="$TEST_IMG.nounref" +TEST_IMG="$NOUNREF_IMG" _make_test_img -o "compat=0.10" 128k +# This should immediately fail with an error +$QEMU_IO -c 'reopen -o discard-no-unref=on' "$NOUNREF_IMG" | _filter_qemu_io + +echo "# Create two compat=1.1 images and fill them with identical data" +_make_test_img -o "compat=1.1" 128k +TEST_IMG="$NOUNREF_IMG" _make_test_img -o "compat=1.1" 128k +$QEMU_IO -c 'write -P 0xaa 0 128k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'write -P 0xaa 0 128k' "$NOUNREF_IMG" | _filter_qemu_io + +echo "# Enable 'discard-no-unref' in one of them, discard 2nd cluster in both" +$QEMU_IO -c 'discard 64k 64k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'reopen -o discard-no-unref=on' \ + -c 'discard 64k 64k' "$NOUNREF_IMG" | _filter_qemu_io + +echo "# Compare disk usage of the 2 images" +# Don't check the exact disk usage values but rather that they're equal +echo "disk_usage(`basename $TEST_IMG`) - disk_usage(`basename $NOUNREF_IMG`)" \ + "= $(( `disk_usage $TEST_IMG` - `disk_usage $NOUNREF_IMG`))" + +echo "# Check that images are still identical" +$QEMU_IMG compare "$TEST_IMG" "$NOUNREF_IMG" + +echo "# Output of qemu-img map for the image with dropped reference" +$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map +echo "# Output of qemu-img map for the image with kept reference" +$QEMU_IMG map --output=json "$NOUNREF_IMG" | _filter_qemu_img_map + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/290.out b/tests/qemu-iotests/290.out index 22b476594f..f790feae81 100644 --- a/tests/qemu-iotests/290.out +++ b/tests/qemu-iotests/290.out @@ -58,4 +58,32 @@ read 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) # Output of qemu-img map Offset Length Mapped to File + +### Test 'qemu-io -c discard' with 'discard-no-unref' option enabled + +# Check that qcow2 v2 images don't support 'discard-no-unref' option +Formatting 'TEST_DIR/t.IMGFMT.nounref', fmt=IMGFMT size=131072 +qemu-io: discard-no-unref is only supported since qcow2 version 3 +# Create two compat=1.1 images and fill them with identical data +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 +Formatting 'TEST_DIR/t.IMGFMT.nounref', fmt=IMGFMT size=131072 +wrote 131072/131072 bytes at offset 0 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 131072/131072 bytes at offset 0 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +# Enable 'discard-no-unref' in one of them, discard 2nd cluster in both +discard 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +discard 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +# Compare disk usage of the 2 images +disk_usage(t.qcow2) - disk_usage(t.qcow2.nounref) = 0 +# Check that images are still identical +Images are identical. +# Output of qemu-img map for the image with dropped reference +[{ "start": 0, "length": 65536, "depth": 0, "present": true, "zero": false, "data": true, "compressed": false, "offset": OFFSET}, +{ "start": 65536, "length": 65536, "depth": 0, "present": true, "zero": true, "data": false, "compressed": false}] +# Output of qemu-img map for the image with kept reference +[{ "start": 0, "length": 65536, "depth": 0, "present": true, "zero": false, "data": true, "compressed": false, "offset": OFFSET}, +{ "start": 65536, "length": 65536, "depth": 0, "present": true, "zero": true, "data": false, "compressed": false, "offset": OFFSET}] *** done From patchwork Fri Sep 13 16:39:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803828 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CBE9BFC6160 for ; Fri, 13 Sep 2024 16:40:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Kr-0006DM-NJ; Fri, 13 Sep 2024 12:39:53 -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 1sp9Kp-00064q-Du; Fri, 13 Sep 2024 12:39:51 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000q6-7W; Fri, 13 Sep 2024 12:39:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=XP3aSiHd4XPEkZX9lxGhcYqB0XI0vIx025UlNzp5+F4=; b=UoVv9MzKB3uG fJDHcBE3/GJ9jAwf+kKpzHJ+Ytil9uyCBtqj46vIkK7otdatVdq4MkcQRhmqsNlVNe96oePyOnByu 1KDXtvJhB9eVXTAmhZg0Gf3KvbD6R8oL7eFMkWjV9rgWP3r3Fx7cMl8cGW/kj0g23+DqNWp8qlkJX mngbf8cY2Y3VbnQbTJ2PZYV245MITnvc1X7cFWTjBkfS9giz89WRbytc+ffFwI15hplk83mnUYEdT PLF2tBq5GvlqGw2kBAKaynoWrAPSFFyeBSkqns7S9d3YoMtby0J11pIdDet/CwG0NypVwc/blGy3V caM1tX2CLowf227A3WyGDw==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-33; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 07/12] qcow2: add get_sc_range_info() helper for working with subcluster ranges Date: Fri, 13 Sep 2024 19:39:37 +0300 Message-Id: <20240913163942.423050-8-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This helper simply obtains the l2 table parameters of the cluster which contains the given subclusters range. Right now this info is being obtained and used by zero_l2_subclusters(). As we're about to introduce the subclusters discard operation, this helper would let us avoid code duplication. Also introduce struct SubClusterRangeInfo, which would contain all the needed params. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov --- block/qcow2-cluster.c | 140 ++++++++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 32 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 7dff0bd5a1..475f167035 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1915,6 +1915,103 @@ discard_no_unref_any_file(BlockDriverState *bs, uint64_t offset, } } +/* + * Structure containing info about the subclusters range within one cluster. + * + * Since @l2_slice is a strong reference to the l2 table slice containing + * the corresponding l2 entry, it must be explicitly released by + * qcow2_cache_put(). Thus the user must either declare it with g_auto() + * (in which case sc_range_info_cleanup() is called automatically) or do + * the cleanup themselves. + */ +typedef struct SubClusterRangeInfo { + uint64_t *l2_slice; + int l2_index; + uint64_t l2_entry; + uint64_t l2_bitmap; + QCow2ClusterType ctype; + Qcow2Cache *l2_table_cache; +} SubClusterRangeInfo; + +static void sc_range_info_cleanup(SubClusterRangeInfo *scri) +{ + if (scri->l2_table_cache && scri->l2_slice) { + qcow2_cache_put(scri->l2_table_cache, (void **) &scri->l2_slice); + } +} + +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(SubClusterRangeInfo, sc_range_info_cleanup); + +/* + * For a given @offset and @nb_subclusters, fill out the SubClusterRangeInfo + * structure describing the subclusters range and referred to by @scri. + * Only the subclusters which can be independently discarded/zeroized + * (i.e. not compressed or invalid) are considered to be valid here. + * + * The subclusters range is denoted by @offset and @nb_subclusters and must + * not cross the cluster boundary. @offset must be aligned to the subcluster + * size. + * + * Return: 0 if the SubClusterRangeInfo is successfully filled out and the + * subclusters within the given range might be discarded/zeroized; + * -EINVAL if any of the subclusters within the range is invalid; + * -ENOTSUP if the range is contained within a compressed cluster. + */ +static int GRAPH_RDLOCK +get_sc_range_info(BlockDriverState *bs, uint64_t offset, + unsigned nb_subclusters, SubClusterRangeInfo *scri) +{ + BDRVQcow2State *s = bs->opaque; + int ret, sc_cleared, sc_index = offset_to_sc_index(s, offset); + QCow2SubclusterType sctype; + + /* Here we only work with the subclusters within single cluster. */ + assert(nb_subclusters > 0 && nb_subclusters < s->subclusters_per_cluster); + assert(sc_index + nb_subclusters <= s->subclusters_per_cluster); + assert(offset_into_subcluster(s, offset) == 0); + + scri->l2_table_cache = s->l2_table_cache; + + ret = get_cluster_table(bs, offset, &scri->l2_slice, &scri->l2_index); + if (ret < 0) { + goto cleanup; + } + + scri->l2_entry = get_l2_entry(s, scri->l2_slice, scri->l2_index); + scri->l2_bitmap = get_l2_bitmap(s, scri->l2_slice, scri->l2_index); + scri->ctype = qcow2_get_cluster_type(bs, scri->l2_entry); + + sc_cleared = 0; + do { + ret = qcow2_get_subcluster_range_type( + bs, scri->l2_entry, scri->l2_bitmap, sc_index + sc_cleared, + &sctype); + if (ret < 0) { + goto cleanup; + } + + switch (sctype) { + case QCOW2_SUBCLUSTER_COMPRESSED: + /* We cannot partially zeroize/discard compressed clusters. */ + ret = -ENOTSUP; + goto cleanup; + case QCOW2_SUBCLUSTER_INVALID: + ret = -EINVAL; + goto cleanup; + default: + break; + } + + sc_cleared += ret; + } while (sc_cleared < nb_subclusters); + + return 0; + +cleanup: + sc_range_info_cleanup(scri); + return ret; +} + /* * This discards as many clusters of nb_clusters as possible at once (i.e. * all clusters in the same L2 slice) and returns the number of discarded @@ -2127,46 +2224,25 @@ zero_l2_subclusters(BlockDriverState *bs, uint64_t offset, unsigned nb_subclusters) { BDRVQcow2State *s = bs->opaque; - uint64_t *l2_slice; - uint64_t old_l2_bitmap, l2_bitmap; - int l2_index, ret, sc = offset_to_sc_index(s, offset); - - /* For full clusters use zero_in_l2_slice() instead */ - assert(nb_subclusters > 0 && nb_subclusters < s->subclusters_per_cluster); - assert(sc + nb_subclusters <= s->subclusters_per_cluster); - assert(offset_into_subcluster(s, offset) == 0); + uint64_t new_l2_bitmap; + int ret, sc = offset_to_sc_index(s, offset); + g_auto(SubClusterRangeInfo) scri = { 0 }; - ret = get_cluster_table(bs, offset, &l2_slice, &l2_index); + ret = get_sc_range_info(bs, offset, nb_subclusters, &scri); if (ret < 0) { return ret; } - switch (qcow2_get_cluster_type(bs, get_l2_entry(s, l2_slice, l2_index))) { - case QCOW2_CLUSTER_COMPRESSED: - ret = -ENOTSUP; /* We cannot partially zeroize compressed clusters */ - goto out; - case QCOW2_CLUSTER_NORMAL: - case QCOW2_CLUSTER_UNALLOCATED: - break; - default: - g_assert_not_reached(); - } - - old_l2_bitmap = l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index); - - l2_bitmap |= QCOW_OFLAG_SUB_ZERO_RANGE(sc, sc + nb_subclusters); - l2_bitmap &= ~QCOW_OFLAG_SUB_ALLOC_RANGE(sc, sc + nb_subclusters); + new_l2_bitmap = scri.l2_bitmap; + new_l2_bitmap |= QCOW_OFLAG_SUB_ZERO_RANGE(sc, sc + nb_subclusters); + new_l2_bitmap &= ~QCOW_OFLAG_SUB_ALLOC_RANGE(sc, sc + nb_subclusters); - if (old_l2_bitmap != l2_bitmap) { - set_l2_bitmap(s, l2_slice, l2_index, l2_bitmap); - qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); + if (new_l2_bitmap != scri.l2_bitmap) { + set_l2_bitmap(s, scri.l2_slice, scri.l2_index, new_l2_bitmap); + qcow2_cache_entry_mark_dirty(s->l2_table_cache, scri.l2_slice); } - ret = 0; -out: - qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice); - - return ret; + return 0; } int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, From patchwork Fri Sep 13 16:39:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803830 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E51B4FC6168 for ; Fri, 13 Sep 2024 16:40:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Kv-0006Rf-9X; Fri, 13 Sep 2024 12:39:57 -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 1sp9Kp-00064p-96; Fri, 13 Sep 2024 12:39:51 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000q7-7B; Fri, 13 Sep 2024 12:39:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=XammWFul7qcRpkCP4NMJhpfM2XFfCsDtsQffF1B++lg=; b=smcBs0Mn/xa5 BRaXGjB9Vav42q4un+4hECORLXnu7KDGPwzj9kiKaU4hBdWBb3FYI9+N3ipCEfqf3jdXrWuFV4CzY R8dsvPHOsjsGeSKpHejqMMfblkhZwLLbyyAWSBh/0hR/gl8j/Ikg3r+jhVgB9vLPp8kG4qBnZeK+z xsliTa1dHpg4ux07ECfdrNSrX2udrwHJ2Rm1gvO6T0TgUL/IJyQFguisflov0cHqvhXXMWHFlwDxe Rm07gKOCHu5ZJGtrp1vpbJC6XqEcUoFEZSSHLsj961UB19w1VHjUtG1SdiZeP3MRGA0AaEezsUGk7 s6v8hxsB0HZ7t3wp5l3VDQ==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hy-002OPf-3D; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 08/12] qcow2: zeroize the entire cluster when there're no non-zero subclusters Date: Fri, 13 Sep 2024 19:39:38 +0300 Message-Id: <20240913163942.423050-9-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org When zeroizing the last non-zero subclusters within single cluster, it makes sense to go zeroize the entire cluster and go down zero_in_l2_slice() path right away. That way we'd also update the corresponding refcount table. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov Reviewed-by: Hanna Czenczek --- block/qcow2-cluster.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 475f167035..8d39e2f960 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -2221,7 +2221,7 @@ zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, static int coroutine_fn GRAPH_RDLOCK zero_l2_subclusters(BlockDriverState *bs, uint64_t offset, - unsigned nb_subclusters) + unsigned nb_subclusters, int flags) { BDRVQcow2State *s = bs->opaque; uint64_t new_l2_bitmap; @@ -2237,6 +2237,16 @@ zero_l2_subclusters(BlockDriverState *bs, uint64_t offset, new_l2_bitmap |= QCOW_OFLAG_SUB_ZERO_RANGE(sc, sc + nb_subclusters); new_l2_bitmap &= ~QCOW_OFLAG_SUB_ALLOC_RANGE(sc, sc + nb_subclusters); + /* + * If there're no non-zero subclusters left, we might as well zeroize + * the entire cluster. That way we'd also update the refcount table. + */ + if ((new_l2_bitmap & QCOW_L2_BITMAP_ALL_ZEROES) == + QCOW_L2_BITMAP_ALL_ZEROES) { + return zero_in_l2_slice(bs, QEMU_ALIGN_DOWN(offset, s->cluster_size), + 1, flags); + } + if (new_l2_bitmap != scri.l2_bitmap) { set_l2_bitmap(s, scri.l2_slice, scri.l2_index, new_l2_bitmap); qcow2_cache_entry_mark_dirty(s->l2_table_cache, scri.l2_slice); @@ -2293,7 +2303,7 @@ int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, if (head) { ret = zero_l2_subclusters(bs, offset - head, - size_to_subclusters(s, head)); + size_to_subclusters(s, head), flags); if (ret < 0) { goto fail; } @@ -2314,7 +2324,8 @@ int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, } if (tail) { - ret = zero_l2_subclusters(bs, end_offset, size_to_subclusters(s, tail)); + ret = zero_l2_subclusters(bs, end_offset, + size_to_subclusters(s, tail), flags); if (ret < 0) { goto fail; } From patchwork Fri Sep 13 16:39:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803834 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E84B8FC6166 for ; Fri, 13 Sep 2024 16:41:06 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Ks-0006Fq-Au; Fri, 13 Sep 2024 12:39:54 -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 1sp9Kp-000655-Q0; Fri, 13 Sep 2024 12:39:51 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9Km-0000qB-AW; Fri, 13 Sep 2024 12:39:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=6TUH3hWc7yBnsdPjbzKjuhLzm0vMR7kWS8RnMuC3e3s=; b=IkA1j8vllWQK aNtIofazJvAr8V7nP2TEadx9CT/HSb+/xR2RZcgoLw6umCydkJueBCUh+h2JGZvfVRVc/x6YVSmoT SFQJkHQrZ8aIcLVu8YMMoP27Lp+T8+TdhxZmDvMdbvkp3JUGcT3kQPz4+0m9oki02cvoBRH6LySMO eFgiHxWzJjNwbAZCKIGVbNxTbL8cmcLqVZFWUPB3ABc2MvnTUxKXmam7a5RF46n2+9sJExMRXA11d 5WXUGME8CoCz9LAVVNglFumvwkXnWXbv7MswpDGKnbiD4BU8B72eyDYjDQcsKDnIXLZahFXZNEHv5 XkbUjxIiq/58FEA6GF7VHA==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hz-002OPf-09; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 09/12] qcow2: make subclusters discardable Date: Fri, 13 Sep 2024 19:39:39 +0300 Message-Id: <20240913163942.423050-10-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This commit makes the discard operation work on the subcluster level rather than cluster level. It introduces discard_l2_subclusters() function and makes use of it in qcow2 discard implementation, much like it's done with zero_in_l2_slice() / zero_l2_subclusters(). It also changes the qcow2 driver pdiscard_alignment to subcluster_size. That way subcluster-aligned discards lead to actual fallocate(PUNCH_HOLE) operation and free host disk space. This feature will let us gain additional disk space on guest TRIM/discard requests, especially when using large enough clusters (1M, 2M) with subclusters enabled. Also rename qcow2_cluster_discard() -> qcow2_subcluster_discard() to reflect the change. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov --- block/qcow2-cluster.c | 106 +++++++++++++++++++++++++++++++++++++---- block/qcow2-snapshot.c | 6 +-- block/qcow2.c | 25 +++++----- block/qcow2.h | 4 +- tests/qemu-iotests/271 | 2 +- 5 files changed, 117 insertions(+), 26 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 8d39e2f960..3c134a7e80 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -2105,25 +2105,106 @@ discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters, return nb_clusters; } -int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, enum qcow2_discard_type type, - bool full_discard) +static int coroutine_fn GRAPH_RDLOCK +discard_l2_subclusters(BlockDriverState *bs, uint64_t offset, + uint64_t nb_subclusters, + enum qcow2_discard_type type, + bool full_discard) +{ + BDRVQcow2State *s = bs->opaque; + uint64_t new_l2_bitmap, bitmap_alloc_mask, bitmap_zero_mask; + int ret, sc = offset_to_sc_index(s, offset); + g_auto(SubClusterRangeInfo) scri = { 0 }; + + ret = get_sc_range_info(bs, offset, nb_subclusters, &scri); + if (ret < 0) { + return ret; + } + + new_l2_bitmap = scri.l2_bitmap; + bitmap_alloc_mask = QCOW_OFLAG_SUB_ALLOC_RANGE(sc, sc + nb_subclusters); + bitmap_zero_mask = QCOW_OFLAG_SUB_ZERO_RANGE(sc, sc + nb_subclusters); + + new_l2_bitmap &= ~bitmap_alloc_mask; + + /* + * Full discard means we fall through to the backing file, thus we need + * to mark the subclusters as deallocated and clear the corresponding + * zero bits. + * + * Non-full discard means subclusters should be explicitly marked as + * zeroes. In this case QCOW2 specification requires the corresponding + * allocation status bits to be unset as well. If the subclusters are + * deallocated in the first place and there's no backing, the operation + * can be skipped. + */ + if (full_discard) { + new_l2_bitmap &= ~bitmap_zero_mask; + } else if (bs->backing || scri.l2_bitmap & bitmap_alloc_mask) { + new_l2_bitmap |= bitmap_zero_mask; + } + + /* + * If after discarding this range there won't be any allocated subclusters + * left, and new bitmap becomes the same as it'd be after discarding the + * whole cluster, we better discard it entirely. That way we'd also + * update the refcount table. + */ + if ((full_discard && new_l2_bitmap == 0) || + (!full_discard && new_l2_bitmap == QCOW_L2_BITMAP_ALL_ZEROES)) { + return discard_in_l2_slice( + bs, QEMU_ALIGN_DOWN(offset, s->cluster_size), + 1, type, full_discard); + } + + if (scri.l2_bitmap != new_l2_bitmap) { + set_l2_bitmap(s, scri.l2_slice, scri.l2_index, new_l2_bitmap); + qcow2_cache_entry_mark_dirty(s->l2_table_cache, scri.l2_slice); + } + + discard_no_unref_any_file( + bs, (scri.l2_entry & L2E_OFFSET_MASK) + offset_into_cluster(s, offset), + nb_subclusters * s->subcluster_size, scri.ctype, type); + + return 0; +} + +int qcow2_subcluster_discard(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, enum qcow2_discard_type type, + bool full_discard) { BDRVQcow2State *s = bs->opaque; uint64_t end_offset = offset + bytes; uint64_t nb_clusters; + unsigned head, tail; int64_t cleared; int ret; /* Caller must pass aligned values, except at image end */ - assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); - assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) || + assert(QEMU_IS_ALIGNED(offset, s->subcluster_size)); + assert(QEMU_IS_ALIGNED(end_offset, s->subcluster_size) || end_offset == bs->total_sectors << BDRV_SECTOR_BITS); - nb_clusters = size_to_clusters(s, bytes); + head = MIN(end_offset, ROUND_UP(offset, s->cluster_size)) - offset; + offset += head; + + tail = (end_offset >= bs->total_sectors << BDRV_SECTOR_BITS) ? 0 : + end_offset - MAX(offset, start_of_cluster(s, end_offset)); + end_offset -= tail; s->cache_discards = true; + if (head) { + ret = discard_l2_subclusters(bs, offset - head, + size_to_subclusters(s, head), type, + full_discard); + if (ret < 0) { + goto fail; + } + } + + nb_clusters = size_to_clusters(s, end_offset - offset); + /* Each L2 slice is handled by its own loop iteration */ while (nb_clusters > 0) { cleared = discard_in_l2_slice(bs, offset, nb_clusters, type, @@ -2137,6 +2218,15 @@ int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, offset += (cleared * s->cluster_size); } + if (tail) { + ret = discard_l2_subclusters(bs, end_offset, + size_to_subclusters(s, tail), type, + full_discard); + if (ret < 0) { + goto fail; + } + } + ret = 0; fail: s->cache_discards = false; @@ -2286,8 +2376,8 @@ int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, */ if (s->qcow_version < 3) { if (!bs->backing) { - return qcow2_cluster_discard(bs, offset, bytes, - QCOW2_DISCARD_REQUEST, false); + return qcow2_subcluster_discard(bs, offset, bytes, + QCOW2_DISCARD_REQUEST, false); } return -ENOTSUP; } diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 92e47978bf..4e39354d02 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -736,9 +736,9 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) /* The VM state isn't needed any more in the active L1 table; in fact, it * hurts by causing expensive COW for the next snapshot. */ - qcow2_cluster_discard(bs, qcow2_vm_state_offset(s), - ROUND_UP(sn->vm_state_size, s->cluster_size), - QCOW2_DISCARD_NEVER, false); + qcow2_subcluster_discard(bs, qcow2_vm_state_offset(s), + ROUND_UP(sn->vm_state_size, s->cluster_size), + QCOW2_DISCARD_NEVER, false); #ifdef DEBUG_ALLOC { diff --git a/block/qcow2.c b/block/qcow2.c index dd359d241b..c2086d0bd1 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1981,7 +1981,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto); } bs->bl.pwrite_zeroes_alignment = s->subcluster_size; - bs->bl.pdiscard_alignment = s->cluster_size; + bs->bl.pdiscard_alignment = s->subcluster_size; } static int GRAPH_UNLOCKED @@ -4126,19 +4126,19 @@ qcow2_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) return -ENOTSUP; } - if (!QEMU_IS_ALIGNED(offset | bytes, s->cluster_size)) { - assert(bytes < s->cluster_size); + if (!QEMU_IS_ALIGNED(offset | bytes, bs->bl.pdiscard_alignment)) { + assert(bytes < bs->bl.pdiscard_alignment); /* Ignore partial clusters, except for the special case of the * complete partial cluster at the end of an unaligned file */ - if (!QEMU_IS_ALIGNED(offset, s->cluster_size) || + if (!QEMU_IS_ALIGNED(offset, bs->bl.pdiscard_alignment) || offset + bytes != bs->total_sectors * BDRV_SECTOR_SIZE) { return -ENOTSUP; } } qemu_co_mutex_lock(&s->lock); - ret = qcow2_cluster_discard(bs, offset, bytes, QCOW2_DISCARD_REQUEST, - false); + ret = qcow2_subcluster_discard(bs, offset, bytes, QCOW2_DISCARD_REQUEST, + false); qemu_co_mutex_unlock(&s->lock); return ret; } @@ -4349,10 +4349,10 @@ qcow2_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, goto fail; } - ret = qcow2_cluster_discard(bs, ROUND_UP(offset, s->cluster_size), - old_length - ROUND_UP(offset, - s->cluster_size), - QCOW2_DISCARD_ALWAYS, true); + ret = qcow2_subcluster_discard(bs, ROUND_UP(offset, s->cluster_size), + old_length - ROUND_UP(offset, + s->cluster_size), + QCOW2_DISCARD_ALWAYS, true); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to discard cropped clusters"); goto fail; @@ -5046,8 +5046,9 @@ static int GRAPH_RDLOCK qcow2_make_empty(BlockDriverState *bs) * default action for this kind of discard is to pass the discard, * which will ideally result in an actually smaller image file, as * is probably desired. */ - ret = qcow2_cluster_discard(bs, offset, MIN(step, end_offset - offset), - QCOW2_DISCARD_SNAPSHOT, true); + ret = qcow2_subcluster_discard(bs, offset, + MIN(step, end_offset - offset), + QCOW2_DISCARD_SNAPSHOT, true); if (ret < 0) { break; } diff --git a/block/qcow2.h b/block/qcow2.h index 197bdcdf53..a65c185b51 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -953,8 +953,8 @@ void coroutine_fn GRAPH_RDLOCK qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m); int GRAPH_RDLOCK -qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes, - enum qcow2_discard_type type, bool full_discard); +qcow2_subcluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes, + enum qcow2_discard_type type, bool full_discard); int coroutine_fn GRAPH_RDLOCK qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, uint64_t bytes, diff --git a/tests/qemu-iotests/271 b/tests/qemu-iotests/271 index 59a6fafa2f..04c57813c2 100755 --- a/tests/qemu-iotests/271 +++ b/tests/qemu-iotests/271 @@ -518,7 +518,7 @@ done ############################################################ ############################################################ -# Test qcow2_cluster_discard() with full and normal discards +# Test qcow2_subcluster_discard() with full and normal discards for use_backing_file in yes no; do echo echo "### Discarding clusters with non-zero bitmaps (backing file: $use_backing_file) ###" From patchwork Fri Sep 13 16:39:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803829 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EFEEEFC6166 for ; Fri, 13 Sep 2024 16:40:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Le-00012d-Sk; Fri, 13 Sep 2024 12:40:43 -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 1sp9LS-0000CX-H6; Fri, 13 Sep 2024 12:40:32 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9LP-00016L-PC; Fri, 13 Sep 2024 12:40:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=RFuHDVCB6WEL6sCRSt1TXrSgPQ8bKk8dhDHri4p6yHE=; b=oedgI/9oOTUD yLH5xXpMTIc1tKyQu8pw5bVIXMAE3l5oLuSJ0tLPWmQyxODsGITHP00Dd6/oQvl14tZE0QidGW9Fe xyu5emlUY5bMjGv3txk5vzEw9Qff09T9T99sJEfomUVMdR3HW6YZ22kJcKkCfNh1TpvToEFdUkCUp s4x3+v0FfLg2QAdwpiJHVM4LUlUoo4YY+XzJHMbxImo+zAaG32FiW4i0WnG9S/gaQbSuogLQV2HqD avYFgYgij3t1mHOSzBa4lAp347bK3/anYneGaTribUKTvePtxZmHQ1Ugg2q2PrHhtgeGye45ECLeK KTW6YzH7Vc51onMqW/NcsA==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hz-002OPf-0K; Fri, 13 Sep 2024 18:39:39 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 10/12] qcow2: zero_l2_subclusters: fall through to discard operation when requested Date: Fri, 13 Sep 2024 19:39:40 +0300 Message-Id: <20240913163942.423050-11-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org When zeroizing subclusters within single cluster, detect usage of the BDRV_REQ_MAY_UNMAP flag and fall through to the subcluster-based discard operation, much like it's done with the cluster-based discards. That way subcluster-aligned operations "qemu-io -c 'write -z -u ...'" will lead to actual unmap. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov --- block/qcow2-cluster.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 3c134a7e80..53e04eff93 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -2107,15 +2107,16 @@ discard_in_l2_slice(BlockDriverState *bs, uint64_t offset, uint64_t nb_clusters, static int coroutine_fn GRAPH_RDLOCK discard_l2_subclusters(BlockDriverState *bs, uint64_t offset, - uint64_t nb_subclusters, - enum qcow2_discard_type type, - bool full_discard) + uint64_t nb_subclusters, enum qcow2_discard_type type, + bool full_discard, bool uncond_zeroize) { BDRVQcow2State *s = bs->opaque; uint64_t new_l2_bitmap, bitmap_alloc_mask, bitmap_zero_mask; int ret, sc = offset_to_sc_index(s, offset); g_auto(SubClusterRangeInfo) scri = { 0 }; + assert(!(full_discard && uncond_zeroize)); + ret = get_sc_range_info(bs, offset, nb_subclusters, &scri); if (ret < 0) { return ret; @@ -2140,7 +2141,8 @@ discard_l2_subclusters(BlockDriverState *bs, uint64_t offset, */ if (full_discard) { new_l2_bitmap &= ~bitmap_zero_mask; - } else if (bs->backing || scri.l2_bitmap & bitmap_alloc_mask) { + } else if (uncond_zeroize || bs->backing || + scri.l2_bitmap & bitmap_alloc_mask) { new_l2_bitmap |= bitmap_zero_mask; } @@ -2197,7 +2199,7 @@ int qcow2_subcluster_discard(BlockDriverState *bs, uint64_t offset, if (head) { ret = discard_l2_subclusters(bs, offset - head, size_to_subclusters(s, head), type, - full_discard); + full_discard, false); if (ret < 0) { goto fail; } @@ -2221,7 +2223,7 @@ int qcow2_subcluster_discard(BlockDriverState *bs, uint64_t offset, if (tail) { ret = discard_l2_subclusters(bs, end_offset, size_to_subclusters(s, tail), type, - full_discard); + full_discard, false); if (ret < 0) { goto fail; } @@ -2318,6 +2320,18 @@ zero_l2_subclusters(BlockDriverState *bs, uint64_t offset, int ret, sc = offset_to_sc_index(s, offset); g_auto(SubClusterRangeInfo) scri = { 0 }; + /* + * If the request allows discarding subclusters we go down the discard + * path regardless of their allocation status. After the discard + * operation with full_discard=false subclusters are going to be read as + * zeroes anyway. But we make sure that subclusters are explicitly + * zeroed anyway with uncond_zeroize=true. + */ + if (flags & BDRV_REQ_MAY_UNMAP) { + return discard_l2_subclusters(bs, offset, nb_subclusters, + QCOW2_DISCARD_REQUEST, false, true); + } + ret = get_sc_range_info(bs, offset, nb_subclusters, &scri); if (ret < 0) { return ret; From patchwork Fri Sep 13 16:39:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803833 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 472FEFC6160 for ; Fri, 13 Sep 2024 16:41:00 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9Lk-0001Uh-MD; Fri, 13 Sep 2024 12:40:48 -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 1sp9La-0000oe-HO; Fri, 13 Sep 2024 12:40:38 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9LX-00017B-PT; Fri, 13 Sep 2024 12:40:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=BeahmhsOF3u83K+5/zMSfIVWcTV5YzoBEeFsUE4xhFs=; b=QGjOAfoqK2wf YSngJZGQZ2A51WbWDPnA3HBItbtCAYyVP3wSrOVfbbSJvwNtcBQqWpqn8IncTbko1rW0L5NjG0dqE i7AoKtrDryLGe77YNfeF4CWWySOLupwcDmXzmPmcGtaoA5HtX4VzvM2AeOECq72LZJr8iyq+mKx9S roH/8GtpxHbcH1dfnNlnVPksPN1GisDGEKhagOAxHHGGuGQKB+P7lOW/EoL4w/Nyr5B0Oh5RU9QPt H1e2fWO31N/HxZ3dma1gEdpu4NweOkGVp6oBkV9WKXOo687W9dIfivAAjXHW1D54dnKgcKKGcSa/D 9ln4cDY8RWcA8exui3hh9Q==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hz-002OPf-0M; Fri, 13 Sep 2024 18:39:40 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 11/12] iotests/271: add test cases for subcluster-based discard/unmap Date: Fri, 13 Sep 2024 19:39:41 +0300 Message-Id: <20240913163942.423050-12-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add a bunch of test cases covering new subclusters behaviour: unmap of last allocated subclusters; unmap of subclusters within unallocated cluster; discard of unallocated subclusters within a cluster; regular discard of subclusters within a cluster; discard of last allocated subclusters. Also make all discard/unmap operations enable trace point 'file_do_fallocate' so that actual fallocate() calls are visible. Signed-off-by: Andrey Drobyshev Reviewed-by: Alexander Ivanov --- tests/qemu-iotests/271 | 70 +++++++++++++++++++++++++++++--------- tests/qemu-iotests/271.out | 69 ++++++++++++++++++++++++++++++++++--- 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/tests/qemu-iotests/271 b/tests/qemu-iotests/271 index 04c57813c2..8b80682cff 100755 --- a/tests/qemu-iotests/271 +++ b/tests/qemu-iotests/271 @@ -81,6 +81,12 @@ _verify_l2_bitmap() fi } +# Filter out trace params which we don't control (file fd) +_filter_trace_fallocate() +{ + sed -E 's/fd=[0-9]+/fd=N/g' +} + # This should be called as _run_test c=XXX sc=XXX off=XXX len=XXX cmd=XXX # c: cluster number (0 if unset) # sc: subcluster number inside cluster @c (0 if unset) @@ -94,12 +100,13 @@ _verify_l2_bitmap() # discard -> discard _run_test() { - unset c sc off len cmd + unset c sc off len cmd opt for var in "$@"; do eval "$var"; done case "${cmd:-write}" in zero) cmd="write -q -z";; unmap) + opt="--trace enable=file_do_fallocate" cmd="write -q -z -u";; compress) pat=$((${pat:-0} + 1)) @@ -108,6 +115,7 @@ _run_test() pat=$((${pat:-0} + 1)) cmd="write -q -P ${pat}";; discard) + opt="--trace enable=file_do_fallocate" cmd="discard -q";; *) echo "Unknown option $cmd" @@ -121,7 +129,7 @@ _run_test() cmd="$cmd ${offset} ${len}" raw_cmd=$(echo $cmd | sed s/-c//) # Raw images don't support -c echo $cmd | sed 's/-P [0-9][0-9]\?/-P PATTERN/' - $QEMU_IO -c "$cmd" "$TEST_IMG" | _filter_qemu_io + $QEMU_IO $opt -c "$cmd" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_trace_fallocate $QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io _verify_img _verify_l2_bitmap "$c" @@ -202,9 +210,10 @@ for use_backing_file in yes no; do alloc="$(seq 16 31)"; zero="$(seq 0 15)" _run_test sc=0 len=32k cmd=unmap - ### Zero and unmap cluster #0 + ### Zero and unmap second half of cluster #0 (this will unmap it and + ### discard l2 entry) alloc=""; zero="$(seq 0 31)" - _run_test sc=0 len=64k cmd=unmap + _run_test sc=16 len=32k cmd=unmap ### Write subcluster #1 (middle of subcluster) alloc="1"; zero="0 $(seq 2 31)" @@ -439,6 +448,12 @@ for use_backing_file in yes no; do _verify_l2_bitmap 16 _verify_l2_bitmap 17 + # Unmap subclusters #0-#3 of an unallocated cluster #8. Since + # 'write -z -u' doesn't lead to full discard, subclusters should become + # explicitly zeroized + alloc=""; zero="$(seq 0 3)" + _run_test c=8 sc=0 len=8k cmd=unmap + # Cluster-aligned request from clusters #9 to #11 alloc=""; zero="$(seq 0 31)" _run_test c=9 sc=0 len=192k cmd=unmap @@ -523,26 +538,45 @@ for use_backing_file in yes no; do echo echo "### Discarding clusters with non-zero bitmaps (backing file: $use_backing_file) ###" echo + + _reset_img 1M + + # Write first half of cluster #0 and discard another half + alloc="$(seq 0 15)"; zero="" + _run_test sc=0 len=32k + # When discarding unallocated subclusters, they only have to be + # explicitly zeroized when the image has a backing file if [ "$use_backing_file" = "yes" ]; then - _make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 1M + alloc="$(seq 0 15)"; zero="$(seq 16 31)" else - _make_test_img -o extended_l2=on 1M + alloc="$(seq 0 15)"; zero="" fi - # Write clusters #0-#2 and then discard them - $QEMU_IO -c 'write -q 0 128k' "$TEST_IMG" - $QEMU_IO -c 'discard -q 0 128k' "$TEST_IMG" + _run_test sc=16 len=32k cmd=discard + + # Write cluster #0 and discard its subclusters #0-#3 + alloc="$(seq 0 31)"; zero="" + _run_test sc=0 len=64k + alloc="$(seq 4 31)"; zero="$(seq 0 3)" + _run_test sc=0 len=8k cmd=discard + + # Discard remaining subclusters #4-#32. This should unmap the cluster + # and discard its l2 entry + alloc=""; zero="$(seq 0 31)" + _run_test sc=4 len=56k cmd=discard + + # Write clusters #0-#1 and then discard them + alloc="$(seq 0 31)"; zero="" + _run_test sc=0 len=128k # 'qemu-io discard' doesn't do a full discard, it zeroizes the - # cluster, so both clusters have all zero bits set now + # cluster, so both clusters have all zero bits set after discard alloc=""; zero="$(seq 0 31)" - _verify_l2_bitmap 0 + _run_test sc=0 len=128k cmd=discard _verify_l2_bitmap 1 + # Now mark the 2nd half of the subclusters from cluster #0 as unallocated poke_file "$TEST_IMG" $(($l2_offset+8)) "\x00\x00" + # Discard cluster #0 again to see how the zero bits have changed - $QEMU_IO -c 'discard -q 0 64k' "$TEST_IMG" - # And do a full discard of cluster #1 by shrinking and growing the image - $QEMU_IMG resize --shrink "$TEST_IMG" 64k - $QEMU_IMG resize "$TEST_IMG" 1M # A normal discard sets all 'zero' bits only if the image has a # backing file, otherwise it won't touch them. if [ "$use_backing_file" = "yes" ]; then @@ -550,7 +584,11 @@ for use_backing_file in yes no; do else alloc=""; zero="$(seq 0 15)" fi - _verify_l2_bitmap 0 + _run_test sc=0 len=64k cmd=discard + + # And do a full discard of cluster #1 by shrinking and growing the image + $QEMU_IMG resize --shrink "$TEST_IMG" 64k + $QEMU_IMG resize "$TEST_IMG" 1M # A full discard should clear the L2 entry completely. However # when growing an image with a backing file the new clusters are # zeroized to hide the stale data from the backing file diff --git a/tests/qemu-iotests/271.out b/tests/qemu-iotests/271.out index 0b24d50159..c03e4c9bc2 100644 --- a/tests/qemu-iotests/271.out +++ b/tests/qemu-iotests/271.out @@ -29,14 +29,17 @@ L2 entry #0: 0x8000000000050000 ffffffff00000000 write -q -P PATTERN 0 64k L2 entry #0: 0x8000000000050000 00000000ffffffff write -q -z -u 0 32k +file_do_fallocate fd=N mode=0x03 offset=327680 len=32768 L2 entry #0: 0x8000000000050000 0000ffffffff0000 -write -q -z -u 0 64k +write -q -z -u 32k 32k +file_do_fallocate fd=N mode=0x03 offset=327680 len=65536 L2 entry #0: 0x0000000000000000 ffffffff00000000 write -q -P PATTERN 3k 512 L2 entry #0: 0x8000000000050000 fffffffd00000002 write -q -P PATTERN 0 64k L2 entry #0: 0x8000000000050000 00000000ffffffff discard -q 0 64k +file_do_fallocate fd=N mode=0x03 offset=327680 len=65536 L2 entry #0: 0x0000000000000000 ffffffff00000000 write -q -c -P PATTERN 0 64k L2 entry #0: 0x4000000000050000 0000000000000000 @@ -71,14 +74,17 @@ L2 entry #0: 0x8000000000050000 ffffffff00000000 write -q -P PATTERN 0 64k L2 entry #0: 0x8000000000050000 00000000ffffffff write -q -z -u 0 32k +file_do_fallocate fd=N mode=0x03 offset=327680 len=32768 L2 entry #0: 0x8000000000050000 0000ffffffff0000 -write -q -z -u 0 64k +write -q -z -u 32k 32k +file_do_fallocate fd=N mode=0x03 offset=327680 len=65536 L2 entry #0: 0x0000000000000000 ffffffff00000000 write -q -P PATTERN 3k 512 L2 entry #0: 0x8000000000050000 fffffffd00000002 write -q -P PATTERN 0 64k L2 entry #0: 0x8000000000050000 00000000ffffffff discard -q 0 64k +file_do_fallocate fd=N mode=0x03 offset=327680 len=65536 L2 entry #0: 0x0000000000000000 ffffffff00000000 write -q -c -P PATTERN 0 64k L2 entry #0: 0x4000000000050000 0000000000000000 @@ -301,15 +307,20 @@ L2 entry #14: 0x80000000000a0000 00000000ffffffff L2 entry #15: 0x80000000000b0000 00000000ffffffff L2 entry #16: 0x80000000000c0000 00000000ffffffff L2 entry #17: 0x80000000000d0000 00000000ffffffff +write -q -z -u 512k 8k +L2 entry #8: 0x0000000000000000 0000000f00000000 write -q -z -u 576k 192k +file_do_fallocate fd=N mode=0x03 offset=327680 len=196608 L2 entry #9: 0x0000000000000000 ffffffff00000000 L2 entry #10: 0x0000000000000000 ffffffff00000000 L2 entry #11: 0x0000000000000000 ffffffff00000000 write -q -z -u 800k 128k +file_do_fallocate fd=N mode=0x03 offset=557056 len=131072 L2 entry #12: 0x8000000000080000 ffff00000000ffff L2 entry #13: 0x0000000000000000 ffffffff00000000 L2 entry #14: 0x80000000000a0000 0000ffffffff0000 write -q -z -u 991k 128k +file_do_fallocate fd=N mode=0x03 offset=753664 len=129024 L2 entry #15: 0x80000000000b0000 ffff00000000ffff L2 entry #16: 0x0000000000000000 ffffffff00000000 L2 entry #17: 0x80000000000d0000 00007fffffff8000 @@ -339,6 +350,7 @@ L2 entry #27: 0x4000000000120000 0000000000000000 write -q -c -P PATTERN 1792k 64k L2 entry #28: 0x4000000000130000 0000000000000000 write -q -z -u 1152k 192k +file_do_fallocate fd=N mode=0x03 offset=327680 len=196608 L2 entry #18: 0x0000000000000000 ffffffff00000000 L2 entry #19: 0x0000000000000000 ffffffff00000000 L2 entry #20: 0x0000000000000000 ffffffff00000000 @@ -351,6 +363,8 @@ L2 entry #24: 0x8000000000090000 00000000ffffffff L2 entry #25: 0x80000000000e0000 00000000ffffffff L2 entry #26: 0x80000000000f0000 00000000ffffffff write -q -z -u 1759k 128k +file_do_fallocate fd=N mode=0x03 offset=819200 len=32768 +file_do_fallocate fd=N mode=0x03 offset=1245184 len=65536 L2 entry #27: 0x80000000000c0000 ffff00000000ffff L2 entry #28: 0x0000000000000000 ffffffff00000000 L2 entry #29: 0x8000000000100000 00007fff00008000 @@ -369,15 +383,20 @@ L2 entry #14: 0x80000000000a0000 00000000ffffffff L2 entry #15: 0x80000000000b0000 00000000ffffffff L2 entry #16: 0x80000000000c0000 00000000ffffffff L2 entry #17: 0x80000000000d0000 00000000ffffffff +write -q -z -u 512k 8k +L2 entry #8: 0x0000000000000000 0000000f00000000 write -q -z -u 576k 192k +file_do_fallocate fd=N mode=0x03 offset=327680 len=196608 L2 entry #9: 0x0000000000000000 ffffffff00000000 L2 entry #10: 0x0000000000000000 ffffffff00000000 L2 entry #11: 0x0000000000000000 ffffffff00000000 write -q -z -u 800k 128k +file_do_fallocate fd=N mode=0x03 offset=557056 len=131072 L2 entry #12: 0x8000000000080000 ffff00000000ffff L2 entry #13: 0x0000000000000000 ffffffff00000000 L2 entry #14: 0x80000000000a0000 0000ffffffff0000 write -q -z -u 991k 128k +file_do_fallocate fd=N mode=0x03 offset=753664 len=129024 L2 entry #15: 0x80000000000b0000 ffff00000000ffff L2 entry #16: 0x0000000000000000 ffffffff00000000 L2 entry #17: 0x80000000000d0000 00007fffffff8000 @@ -407,6 +426,7 @@ L2 entry #27: 0x4000000000120000 0000000000000000 write -q -c -P PATTERN 1792k 64k L2 entry #28: 0x4000000000130000 0000000000000000 write -q -z -u 1152k 192k +file_do_fallocate fd=N mode=0x03 offset=327680 len=196608 L2 entry #18: 0x0000000000000000 ffffffff00000000 L2 entry #19: 0x0000000000000000 ffffffff00000000 L2 entry #20: 0x0000000000000000 ffffffff00000000 @@ -419,28 +439,69 @@ L2 entry #24: 0x8000000000090000 00000000ffffffff L2 entry #25: 0x80000000000e0000 00000000ffffffff L2 entry #26: 0x80000000000f0000 00000000ffffffff write -q -z -u 1759k 128k +file_do_fallocate fd=N mode=0x03 offset=819200 len=32768 +file_do_fallocate fd=N mode=0x03 offset=1245184 len=65536 L2 entry #27: 0x80000000000c0000 ffff00000000ffff L2 entry #28: 0x0000000000000000 ffffffff00000000 L2 entry #29: 0x0000000000000000 0000ffff00000000 ### Discarding clusters with non-zero bitmaps (backing file: yes) ### +Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=1048576 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +write -q -P PATTERN 0 32k +L2 entry #0: 0x8000000000050000 000000000000ffff +discard -q 32k 32k +file_do_fallocate fd=N mode=0x03 offset=360448 len=32768 +L2 entry #0: 0x8000000000050000 ffff00000000ffff +write -q -P PATTERN 0 64k +L2 entry #0: 0x8000000000050000 00000000ffffffff +discard -q 0 8k +file_do_fallocate fd=N mode=0x03 offset=327680 len=8192 +L2 entry #0: 0x8000000000050000 0000000ffffffff0 +discard -q 8k 56k +file_do_fallocate fd=N mode=0x03 offset=327680 len=65536 +L2 entry #0: 0x0000000000000000 ffffffff00000000 +write -q -P PATTERN 0 128k +L2 entry #0: 0x8000000000050000 00000000ffffffff +discard -q 0 128k +file_do_fallocate fd=N mode=0x03 offset=327680 len=131072 L2 entry #0: 0x0000000000000000 ffffffff00000000 L2 entry #1: 0x0000000000000000 ffffffff00000000 +discard -q 0 64k +L2 entry #0: 0x0000000000000000 ffffffff00000000 Image resized. Image resized. -L2 entry #0: 0x0000000000000000 ffffffff00000000 L2 entry #1: 0x0000000000000000 ffffffff00000000 ### Discarding clusters with non-zero bitmaps (backing file: no) ### +Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +write -q -P PATTERN 0 32k +L2 entry #0: 0x8000000000050000 000000000000ffff +discard -q 32k 32k +file_do_fallocate fd=N mode=0x03 offset=360448 len=32768 +L2 entry #0: 0x8000000000050000 000000000000ffff +write -q -P PATTERN 0 64k +L2 entry #0: 0x8000000000050000 00000000ffffffff +discard -q 0 8k +file_do_fallocate fd=N mode=0x03 offset=327680 len=8192 +L2 entry #0: 0x8000000000050000 0000000ffffffff0 +discard -q 8k 56k +file_do_fallocate fd=N mode=0x03 offset=327680 len=65536 +L2 entry #0: 0x0000000000000000 ffffffff00000000 +write -q -P PATTERN 0 128k +L2 entry #0: 0x8000000000050000 00000000ffffffff +discard -q 0 128k +file_do_fallocate fd=N mode=0x03 offset=327680 len=131072 L2 entry #0: 0x0000000000000000 ffffffff00000000 L2 entry #1: 0x0000000000000000 ffffffff00000000 +discard -q 0 64k +L2 entry #0: 0x0000000000000000 0000ffff00000000 Image resized. Image resized. -L2 entry #0: 0x0000000000000000 0000ffff00000000 L2 entry #1: 0x0000000000000000 0000000000000000 ### Corrupted L2 entries - read test (allocated) ### From patchwork Fri Sep 13 16:39:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Drobyshev X-Patchwork-Id: 13803831 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 43DA3FC616A for ; Fri, 13 Sep 2024 16:40:57 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sp9LW-0000LY-DJ; Fri, 13 Sep 2024 12:40:35 -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 1sp9LI-0007ul-Nr; Fri, 13 Sep 2024 12:40:21 -0400 Received: from relay.virtuozzo.com ([130.117.225.111]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sp9LG-00015Z-Un; Fri, 13 Sep 2024 12:40:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=MIME-Version:Message-Id:Date:Subject:From: Content-Type; bh=Of+BGFkX4T73fvOvveXGD/8FZywciz8d+w+vmJhE8o8=; b=tvXwKb/KSIxC An5LpO3/0uVf1RjWHIUY+mKpM4sERYQEkboW42dqUtT9A1/yHucs1LRbD42B0OAw5GAy/S4hSCluZ 2gAkxGnMuFafddc/JlgZOGx7y5OKcIPn99/myP1qyGqAeI6vsq82M6QlKXTqqLE9DW06QxvioY44U riCrCV2np0b8g6Y8b23JIzIwR1kqYuTTAnArfThQ3FGeWmMJGK8EFnKuuT4Um3pcm2xu5zC1qHuqj Cf0emyoA79h9J3+7gfsHACflLkLV7gFc9e9VDi7jDlpv1QQkph2Rw55oDDt9BRE9Sqr2KUhDdDfUZ 5mMpUyriqRAJi1HKRVaZ9g==; Received: from [130.117.225.1] (helo=dev005.ch-qa.vzint.dev) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1sp9Hz-002OPf-0Y; Fri, 13 Sep 2024 18:39:40 +0200 From: Andrey Drobyshev To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, hreitz@redhat.com, kwolf@redhat.com, eblake@redhat.com, stefanha@redhat.com, berto@igalia.com, andrey.drobyshev@virtuozzo.com, den@virtuozzo.com Subject: [PATCH v3 12/12] qcow2: add discard-subclusters option Date: Fri, 13 Sep 2024 19:39:42 +0300 Message-Id: <20240913163942.423050-13-andrey.drobyshev@virtuozzo.com> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> References: <20240913163942.423050-1-andrey.drobyshev@virtuozzo.com> MIME-Version: 1.0 Received-SPF: pass client-ip=130.117.225.111; envelope-from=andrey.drobyshev@virtuozzo.com; helo=relay.virtuozzo.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Introduce Qcow2 runtime boolean option "discard-subclusters". This option influences discard alignment value (either cluster_size or subcluster_size) and essentially makes subcluster-based discard optional. We disable it by default. Also tweak iotests/271 to enable this option and really test subcluster based discards. Signed-off-by: Andrey Drobyshev --- block/qcow2.c | 21 ++++++++++++++++++++- block/qcow2.h | 2 ++ tests/qemu-iotests/271 | 10 ++++++---- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index c2086d0bd1..7c38a5be41 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -685,6 +685,7 @@ static const char *const mutable_opts[] = { QCOW2_OPT_DISCARD_SNAPSHOT, QCOW2_OPT_DISCARD_OTHER, QCOW2_OPT_DISCARD_NO_UNREF, + QCOW2_OPT_DISCARD_SUBCLUSTERS, QCOW2_OPT_OVERLAP, QCOW2_OPT_OVERLAP_TEMPLATE, QCOW2_OPT_OVERLAP_MAIN_HEADER, @@ -734,6 +735,11 @@ static QemuOptsList qcow2_runtime_opts = { .type = QEMU_OPT_BOOL, .help = "Do not unreference discarded clusters", }, + { + .name = QCOW2_OPT_DISCARD_SUBCLUSTERS, + .type = QEMU_OPT_BOOL, + .help = "Allow subcluster aligned discard requests", + }, { .name = QCOW2_OPT_OVERLAP, .type = QEMU_OPT_STRING, @@ -978,6 +984,7 @@ typedef struct Qcow2ReopenState { int overlap_check; bool discard_passthrough[QCOW2_DISCARD_MAX]; bool discard_no_unref; + bool discard_subclusters; uint64_t cache_clean_interval; QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */ } Qcow2ReopenState; @@ -1157,6 +1164,16 @@ qcow2_update_options_prepare(BlockDriverState *bs, Qcow2ReopenState *r, goto fail; } + r->discard_subclusters = + qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SUBCLUSTERS, false); + if (r->discard_subclusters && !has_subclusters(s)) { + error_setg(errp, + "Image doesn't have extended L2 entries, but option " + "'discard-subclusters' is enabled"); + ret = -EINVAL; + goto fail; + } + switch (s->crypt_method_header) { case QCOW_CRYPT_NONE: if (encryptfmt) { @@ -1238,6 +1255,7 @@ static void qcow2_update_options_commit(BlockDriverState *bs, } s->discard_no_unref = r->discard_no_unref; + s->discard_subclusters = r->discard_subclusters; if (s->cache_clean_interval != r->cache_clean_interval) { cache_clean_timer_del(bs); @@ -1981,7 +1999,8 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto); } bs->bl.pwrite_zeroes_alignment = s->subcluster_size; - bs->bl.pdiscard_alignment = s->subcluster_size; + bs->bl.pdiscard_alignment = s->discard_subclusters ? + s->subcluster_size : s->cluster_size; } static int GRAPH_UNLOCKED diff --git a/block/qcow2.h b/block/qcow2.h index a65c185b51..4e91bdde3f 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -134,6 +134,7 @@ #define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot" #define QCOW2_OPT_DISCARD_OTHER "pass-discard-other" #define QCOW2_OPT_DISCARD_NO_UNREF "discard-no-unref" +#define QCOW2_OPT_DISCARD_SUBCLUSTERS "discard-subclusters" #define QCOW2_OPT_OVERLAP "overlap-check" #define QCOW2_OPT_OVERLAP_TEMPLATE "overlap-check.template" #define QCOW2_OPT_OVERLAP_MAIN_HEADER "overlap-check.main-header" @@ -387,6 +388,7 @@ typedef struct BDRVQcow2State { bool discard_passthrough[QCOW2_DISCARD_MAX]; bool discard_no_unref; + bool discard_subclusters; int overlap_check; /* bitmask of Qcow2MetadataOverlap values */ bool signaled_corruption; diff --git a/tests/qemu-iotests/271 b/tests/qemu-iotests/271 index 8b80682cff..d7cf3c459b 100755 --- a/tests/qemu-iotests/271 +++ b/tests/qemu-iotests/271 @@ -100,13 +100,14 @@ _filter_trace_fallocate() # discard -> discard _run_test() { - unset c sc off len cmd opt + unset c sc off len cmd trace opt for var in "$@"; do eval "$var"; done case "${cmd:-write}" in zero) cmd="write -q -z";; unmap) - opt="--trace enable=file_do_fallocate" + trace="--trace enable=file_do_fallocate" + opt="-c reopen -o discard-subclusters=on" cmd="write -q -z -u";; compress) pat=$((${pat:-0} + 1)) @@ -115,7 +116,8 @@ _run_test() pat=$((${pat:-0} + 1)) cmd="write -q -P ${pat}";; discard) - opt="--trace enable=file_do_fallocate" + trace="--trace enable=file_do_fallocate" + opt="-c reopen -o discard-subclusters=on" cmd="discard -q";; *) echo "Unknown option $cmd" @@ -129,7 +131,7 @@ _run_test() cmd="$cmd ${offset} ${len}" raw_cmd=$(echo $cmd | sed s/-c//) # Raw images don't support -c echo $cmd | sed 's/-P [0-9][0-9]\?/-P PATTERN/' - $QEMU_IO $opt -c "$cmd" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_trace_fallocate + $QEMU_IO $trace ${opt:+ "$opt"} -c "$cmd" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_trace_fallocate $QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io _verify_img _verify_l2_bitmap "$c"