From nobody Sat Nov 15 19:39:04 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1748618206111524.3315621775344; Fri, 30 May 2025 08:16:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uL1Pb-0004WA-5v; Fri, 30 May 2025 11:12:47 -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 1uL1PZ-0004Rh-0s; Fri, 30 May 2025 11:12:45 -0400 Received: from proxmox-new.maurer-it.com ([94.136.29.106]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uL1PV-0002Kf-GZ; Fri, 30 May 2025 11:12:44 -0400 Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id E19E244B02; Fri, 30 May 2025 17:11:47 +0200 (CEST) From: Fiona Ebner To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, kwolf@redhat.com, den@virtuozzo.com, andrey.drobyshev@virtuozzo.com, hreitz@redhat.com, stefanha@redhat.com, eblake@redhat.com, jsnow@redhat.com, vsementsov@yandex-team.ru, xiechanglong.d@gmail.com, wencongyang2@huawei.com, berto@igalia.com, fam@euphon.net, ari@tuxera.com Subject: [PATCH v4 21/48] iotests/graph-changes-while-io: add test case with removal of lower snapshot Date: Fri, 30 May 2025 17:10:58 +0200 Message-Id: <20250530151125.955508-22-f.ebner@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250530151125.955508-1-f.ebner@proxmox.com> References: <20250530151125.955508-1-f.ebner@proxmox.com> MIME-Version: 1.0 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=94.136.29.106; envelope-from=f.ebner@proxmox.com; helo=proxmox-new.maurer-it.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1748618208128116600 Content-Type: text/plain; charset="utf-8" From: Andrey Drobyshev This case is catching potential deadlock which takes place when job-dismiss is issued when I/O requests are processed in a separate iothread. See https://mail.gnu.org/archive/html/qemu-devel/2025-04/msg04421.html Signed-off-by: Andrey Drobyshev [FE: re-use top image and rename snap1->mid as suggested by Kevin Wolf remove image file after test as suggested by Kevin Wolf add type annotation for function argument to make mypy happy] Signed-off-by: Fiona Ebner --- .../qemu-iotests/tests/graph-changes-while-io | 101 ++++++++++++++++-- .../tests/graph-changes-while-io.out | 4 +- 2 files changed, 96 insertions(+), 9 deletions(-) diff --git a/tests/qemu-iotests/tests/graph-changes-while-io b/tests/qemu-i= otests/tests/graph-changes-while-io index 35489e3b5e..dca1167b6d 100755 --- a/tests/qemu-iotests/tests/graph-changes-while-io +++ b/tests/qemu-iotests/tests/graph-changes-while-io @@ -27,6 +27,7 @@ from iotests import imgfmt, qemu_img, qemu_img_create, qe= mu_io, \ =20 =20 top =3D os.path.join(iotests.test_dir, 'top.img') +mid =3D os.path.join(iotests.test_dir, 'mid.img') nbd_sock =3D os.path.join(iotests.sock_dir, 'nbd.sock') =20 =20 @@ -59,6 +60,15 @@ class TestGraphChangesWhileIO(QMPTestCase): self.qsd.stop() os.remove(top) =20 + def _wait_for_blockjob(self, status: str) -> None: + done =3D False + while not done: + for event in self.qsd.get_qmp().get_events(wait=3D10.0): + if event['event'] !=3D 'JOB_STATUS_CHANGE': + continue + if event['data']['status'] =3D=3D status: + done =3D True + def test_blockdev_add_while_io(self) -> None: # Run qemu-img bench in the background bench_thr =3D Thread(target=3Ddo_qemu_img_bench) @@ -117,16 +127,93 @@ class TestGraphChangesWhileIO(QMPTestCase): 'device': 'job0', }) =20 - cancelled =3D False - while not cancelled: - for event in self.qsd.get_qmp().get_events(wait=3D10.0): - if event['event'] !=3D 'JOB_STATUS_CHANGE': - continue - if event['data']['status'] =3D=3D 'null': - cancelled =3D True + self._wait_for_blockjob('null') =20 bench_thr.join() =20 + def test_remove_lower_snapshot_while_io(self) -> None: + # Run qemu-img bench in the background + bench_thr =3D Thread(target=3Ddo_qemu_img_bench, args=3D(100000, )) + bench_thr.start() + + # While I/O is performed on 'node0' node, consequently add 2 snaps= hots + # on top of it, then remove (commit) them starting from lower one. + while bench_thr.is_alive(): + # Recreate snapshot images on every iteration + qemu_img_create('-f', imgfmt, mid, '1G') + qemu_img_create('-f', imgfmt, top, '1G') + + self.qsd.cmd('blockdev-add', { + 'driver': imgfmt, + 'node-name': 'mid', + 'file': { + 'driver': 'file', + 'filename': mid + } + }) + + self.qsd.cmd('blockdev-snapshot', { + 'node': 'node0', + 'overlay': 'mid', + }) + + self.qsd.cmd('blockdev-add', { + 'driver': imgfmt, + 'node-name': 'top', + 'file': { + 'driver': 'file', + 'filename': top + } + }) + + self.qsd.cmd('blockdev-snapshot', { + 'node': 'mid', + 'overlay': 'top', + }) + + self.qsd.cmd('block-commit', { + 'job-id': 'commit-mid', + 'device': 'top', + 'top-node': 'mid', + 'base-node': 'node0', + 'auto-finalize': True, + 'auto-dismiss': False, + }) + + self._wait_for_blockjob('concluded') + self.qsd.cmd('job-dismiss', { + 'id': 'commit-mid', + }) + + self.qsd.cmd('block-commit', { + 'job-id': 'commit-top', + 'device': 'top', + 'top-node': 'top', + 'base-node': 'node0', + 'auto-finalize': True, + 'auto-dismiss': False, + }) + + self._wait_for_blockjob('ready') + self.qsd.cmd('job-complete', { + 'id': 'commit-top', + }) + + self._wait_for_blockjob('concluded') + self.qsd.cmd('job-dismiss', { + 'id': 'commit-top', + }) + + self.qsd.cmd('blockdev-del', { + 'node-name': 'mid' + }) + self.qsd.cmd('blockdev-del', { + 'node-name': 'top' + }) + + bench_thr.join() + os.remove(mid) + if __name__ =3D=3D '__main__': # Format must support raw backing files iotests.main(supported_fmts=3D['qcow', 'qcow2', 'qed'], diff --git a/tests/qemu-iotests/tests/graph-changes-while-io.out b/tests/qe= mu-iotests/tests/graph-changes-while-io.out index fbc63e62f8..8d7e996700 100644 --- a/tests/qemu-iotests/tests/graph-changes-while-io.out +++ b/tests/qemu-iotests/tests/graph-changes-while-io.out @@ -1,5 +1,5 @@ -.. +... ---------------------------------------------------------------------- -Ran 2 tests +Ran 3 tests =20 OK --=20 2.39.5