From nobody Mon Feb 9 03:54:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1647275685732125.15983842960884; Mon, 14 Mar 2022 09:34:45 -0700 (PDT) Received: from localhost ([::1]:43046 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nTnee-0003YL-QS for importer@patchew.org; Mon, 14 Mar 2022 12:34:44 -0400 Received: from eggs.gnu.org ([209.51.188.92]:53888) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nTnXc-0001Pm-9D for qemu-devel@nongnu.org; Mon, 14 Mar 2022 12:27:28 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:47400) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nTnXa-0005l7-N2 for qemu-devel@nongnu.org; Mon, 14 Mar 2022 12:27:28 -0400 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-601-MnCnUHHfMLWjeac0yw7IQA-1; Mon, 14 Mar 2022 12:27:23 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9973A2999B2A; Mon, 14 Mar 2022 16:27:22 +0000 (UTC) Received: from localhost (unknown [10.39.194.97]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 55E5A2D460; Mon, 14 Mar 2022 16:27:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1647275246; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uu5wEasI+3ljpLl6z5hpzxYb/IK7YQF8kQRvZ3I7iS4=; b=BnUI0FF05DFWAVrjMe0tLecj3MDCdUyv3v96S3Wr6qIe+PywqfKzw1VlMfC6QPqCdjDNet rSCiPlIpvxQ4JVGWJD09qZxEPqPb8RmBfapUfgk1pxtL9W1bFZsdopprdPpN9x96JjJXnV lVUAExLss5WBcpeuYdkhpg3B5LoESds= X-MC-Unique: MnCnUHHfMLWjeac0yw7IQA-1 From: Hanna Reitz To: qemu-block@nongnu.org Subject: [PATCH for-7.0 1/2] block/vmdk: Fix reopening bs->file Date: Mon, 14 Mar 2022 17:27:18 +0100 Message-Id: <20220314162719.65384-2-hreitz@redhat.com> In-Reply-To: <20220314162719.65384-1-hreitz@redhat.com> References: <20220314162719.65384-1-hreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=hreitz@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Hanna Reitz , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1647275687368100001 Content-Type: text/plain; charset="utf-8" VMDK disk data is stored in extents, which may or may not be separate from bs->file. VmdkExtent.file points to where they are stored. Each that is stored in bs->file will simply reuse the exact pointer value of bs->file. (That is why vmdk_free_extents() will unref VmdkExtent.file (e->file) only if e->file !=3D bs->file.) Reopen operations can change bs->file (they will replace the whole BdrvChild object, not just the BDS stored in that BdrvChild), and then we will need to change all .file pointers of all such VmdkExtents to point to the new BdrvChild. In vmdk_reopen_prepare(), we have to check which VmdkExtents are affected, and in vmdk_reopen_commit(), we can modify them. We have to split this because: - The new BdrvChild is created only after prepare, so we can change VmdkExtent.file only in commit - In commit, there no longer is any (valid) reference to the old BdrvChild object, so there would be nothing to compare VmdkExtent.file against to see whether it was equal to bs->file before reopening (There is BDRVReopenState.old_file_bs, but the old bs->file BdrvChild's .bs pointer will be NULL-ed when the new BdrvChild is created, and so we cannot compare VmdkExtent.file->bs against BDRVReopenState.old_file_bs) Signed-off-by: Hanna Reitz --- block/vmdk.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/block/vmdk.c b/block/vmdk.c index 37c0946066..38e5ab3806 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -178,6 +178,10 @@ typedef struct BDRVVmdkState { char *create_type; } BDRVVmdkState; =20 +typedef struct BDRVVmdkReopenState { + bool *extents_using_bs_file; +} BDRVVmdkReopenState; + typedef struct VmdkMetaData { unsigned int l1_index; unsigned int l2_index; @@ -400,15 +404,63 @@ static int vmdk_is_cid_valid(BlockDriverState *bs) return 1; } =20 -/* We have nothing to do for VMDK reopen, stubs just return success */ static int vmdk_reopen_prepare(BDRVReopenState *state, BlockReopenQueue *queue, Error **errp) { + BDRVVmdkState *s; + BDRVVmdkReopenState *rs; + int i; + assert(state !=3D NULL); assert(state->bs !=3D NULL); + assert(state->opaque =3D=3D NULL); + + s =3D state->bs->opaque; + + rs =3D g_new0(BDRVVmdkReopenState, 1); + state->opaque =3D rs; + + /* + * Check whether there are any extents stored in bs->file; if bs->file + * changes, we will need to update their .file pointers to follow suit + */ + rs->extents_using_bs_file =3D g_new(bool, s->num_extents); + for (i =3D 0; i < s->num_extents; i++) { + rs->extents_using_bs_file[i] =3D s->extents[i].file =3D=3D state->= bs->file; + } + return 0; } =20 +static void vmdk_reopen_clean(BDRVReopenState *state) +{ + BDRVVmdkReopenState *rs =3D state->opaque; + + g_free(rs->extents_using_bs_file); + g_free(rs); + state->opaque =3D NULL; +} + +static void vmdk_reopen_commit(BDRVReopenState *state) +{ + BDRVVmdkState *s =3D state->bs->opaque; + BDRVVmdkReopenState *rs =3D state->opaque; + int i; + + for (i =3D 0; i < s->num_extents; i++) { + if (rs->extents_using_bs_file[i]) { + s->extents[i].file =3D state->bs->file; + } + } + + vmdk_reopen_clean(state); +} + +static void vmdk_reopen_abort(BDRVReopenState *state) +{ + vmdk_reopen_clean(state); +} + static int vmdk_parent_open(BlockDriverState *bs) { char *p_name; @@ -3072,6 +3124,8 @@ static BlockDriver bdrv_vmdk =3D { .bdrv_open =3D vmdk_open, .bdrv_co_check =3D vmdk_co_check, .bdrv_reopen_prepare =3D vmdk_reopen_prepare, + .bdrv_reopen_commit =3D vmdk_reopen_commit, + .bdrv_reopen_abort =3D vmdk_reopen_abort, .bdrv_child_perm =3D bdrv_default_perms, .bdrv_co_preadv =3D vmdk_co_preadv, .bdrv_co_pwritev =3D vmdk_co_pwritev, --=20 2.35.1 From nobody Mon Feb 9 03:54:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 164727556630933.41337542364272; Mon, 14 Mar 2022 09:32:46 -0700 (PDT) Received: from localhost ([::1]:38594 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nTncj-0000Xb-40 for importer@patchew.org; Mon, 14 Mar 2022 12:32:45 -0400 Received: from eggs.gnu.org ([209.51.188.92]:53912) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nTnXf-0001YD-Gd for qemu-devel@nongnu.org; Mon, 14 Mar 2022 12:27:31 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:45197) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nTnXd-0005lT-IX for qemu-devel@nongnu.org; Mon, 14 Mar 2022 12:27:31 -0400 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-6-jqjEgSZxNCaHVl3fAQn3VQ-1; Mon, 14 Mar 2022 12:27:24 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3C613801585; Mon, 14 Mar 2022 16:27:24 +0000 (UTC) Received: from localhost (unknown [10.39.194.97]) by smtp.corp.redhat.com (Postfix) with ESMTPS id EB7102023A09; Mon, 14 Mar 2022 16:27:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1647275248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1R9g94+vMC65XZjqr2KtePUIB0UeFoJjSaSLqLU9Teg=; b=QC1K2ZGZ8kGKYYR78fjj6/yllyEumohEAZXaXhx8i/IYwBLSglB/Zag+9zS7gL1Gxxcegh vC9CYQevektm3ncu0aJBft2dlQ7oo8p/dxAHvfErEmQB/9SLgJi7qFK+rEFVI9oi7kK3zS Dd98pPLAM7E79EM0PiZbptQCffqNUSs= X-MC-Unique: jqjEgSZxNCaHVl3fAQn3VQ-1 From: Hanna Reitz To: qemu-block@nongnu.org Subject: [PATCH for-7.0 2/2] iotests/reopen-file: Test reopening file child Date: Mon, 14 Mar 2022 17:27:19 +0100 Message-Id: <20220314162719.65384-3-hreitz@redhat.com> In-Reply-To: <20220314162719.65384-1-hreitz@redhat.com> References: <20220314162719.65384-1-hreitz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=hreitz@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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: , Cc: Kevin Wolf , Hanna Reitz , qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1647275568859100001 Content-Type: text/plain; charset="utf-8" This should work for all format drivers that support reopening, so test it. (This serves as a regression test for HEAD^: This test used to fail for VMDK before HEAD^.) Signed-off-by: Hanna Reitz --- tests/qemu-iotests/tests/reopen-file | 88 ++++++++++++++++++++++++ tests/qemu-iotests/tests/reopen-file.out | 5 ++ 2 files changed, 93 insertions(+) create mode 100755 tests/qemu-iotests/tests/reopen-file create mode 100644 tests/qemu-iotests/tests/reopen-file.out diff --git a/tests/qemu-iotests/tests/reopen-file b/tests/qemu-iotests/test= s/reopen-file new file mode 100755 index 0000000000..24fd648050 --- /dev/null +++ b/tests/qemu-iotests/tests/reopen-file @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# group: rw quick +# +# Test reopening a format driver's file child +# +# Copyright (C) 2022 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import os +import iotests +from iotests import imgfmt, qemu_img_create, QMPTestCase + + +image_size =3D 1 * 1024 * 1024 +test_img =3D os.path.join(iotests.test_dir, 'test.img') + + +class TestReopenFile(QMPTestCase): + def setUp(self) -> None: + assert qemu_img_create('-f', imgfmt, test_img, str(image_size)) = =3D=3D 0 + + # Add format driver node ('format') on top of the file ('file'), t= hen + # add another raw node ('raw') on top of 'file' so for the reopen = we + # can just switch from 'file' to 'raw' + self.vm =3D iotests.VM() + self.vm.add_blockdev(self.vm.qmp_to_opts({ + 'driver': imgfmt, + 'node-name': 'format', + 'file': { + 'driver': 'file', + 'node-name': 'file', + 'filename': test_img + } + })) + self.vm.add_blockdev(self.vm.qmp_to_opts({ + 'driver': 'raw', + 'node-name': 'raw', + 'file': 'file' + })) + self.vm.launch() + + def tearDown(self) -> None: + self.vm.shutdown() + os.remove(test_img) + + # Check if there was any qemu-io run that failed + if 'Pattern verification failed' in self.vm.get_log(): + print('ERROR: Pattern verification failed:') + print(self.vm.get_log()) + self.fail('qemu-io pattern verification failed') + + def test_reopen_file(self) -> None: + result =3D self.vm.qmp('blockdev-reopen', options=3D[{ + 'driver': imgfmt, + 'node-name': 'format', + 'file': 'raw' + }]) + self.assert_qmp(result, 'return', {}) + + # Do some I/O to the image to see whether it still works + # (Pattern verification will be checked by tearDown()) + result =3D self.vm.qmp('human-monitor-command', + command_line=3D'qemu-io format "write -P 42 0= 64k"') + self.assert_qmp(result, 'return', '') + + result =3D self.vm.qmp('human-monitor-command', + command_line=3D'qemu-io format "read -P 42 0 = 64k"') + self.assert_qmp(result, 'return', '') + + +if __name__ =3D=3D '__main__': + # Must support creating images and reopen + iotests.main(supported_fmts=3D['qcow', 'qcow2', 'qed', 'raw', 'vdi', '= vhdx', + 'vmdk', 'vpc'], + supported_protocols=3D['file']) diff --git a/tests/qemu-iotests/tests/reopen-file.out b/tests/qemu-iotests/= tests/reopen-file.out new file mode 100644 index 0000000000..ae1213e6f8 --- /dev/null +++ b/tests/qemu-iotests/tests/reopen-file.out @@ -0,0 +1,5 @@ +. +---------------------------------------------------------------------- +Ran 1 tests + +OK --=20 2.35.1