From: "Denis V. Lunev" <den@openvz.org>
To: svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com, den@virtuozzo.com
Subject: [PATCH hci-8.0 2/9] iotests/040: cover large and fragmented commit runs #VSTOR-134085
Date: Wed, 30 Sep 2026 13:17:32 +0200 [thread overview]
Message-ID: <20260930111739.3866427-3-den@openvz.org> (raw)
In-Reply-To: <20260930111739.3866427-1-den@openvz.org>
From: Denis V. Lunev <den@openvz.org>
040 never commits runs long enough to span more than one block-status
query, so the answer that commit_iteration() is about to start caching
goes untested.
Add two cases on a base <- mid <- active chain, committing mid so the
job takes the regular commit path rather than active commit, and compare
base against a snapshot of mid taken before the commit. One case mixes
multi-megabyte data, zero and hole runs, the other fragments them down
to single clusters with every transition off the 512K boundary.
Reviewed-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
CC: John Snow <jsnow@redhat.com>
CC: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
tests/qemu-iotests/040 | 102 ++++++++++++++++++++++++++++++++++++-
tests/qemu-iotests/040.out | 4 +-
2 files changed, 103 insertions(+), 3 deletions(-)
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index 5c18e413ec9..e01c9385bae 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -25,13 +25,14 @@
import time
import os
import iotests
-from iotests import qemu_img, qemu_io
+from iotests import qemu_img, qemu_img_create, qemu_io, compare_images
import struct
import errno
backing_img = os.path.join(iotests.test_dir, 'backing.img')
mid_img = os.path.join(iotests.test_dir, 'mid.img')
test_img = os.path.join(iotests.test_dir, 'test.img')
+reference_img = os.path.join(iotests.test_dir, 'reference.img')
class ImageCommitTestCase(iotests.QMPTestCase):
'''Abstract base class for image commit test cases'''
@@ -951,6 +952,105 @@ class TestCommitWithOverriddenBacking(iotests.QMPTestCase):
self.vm.qmp('block-job-complete', device='commit')
self.vm.event_wait('BLOCK_JOB_COMPLETED')
+class TestCommitLargeRuns(iotests.QMPTestCase):
+ """Commit runs long enough to cross commit_iteration()'s cached span."""
+
+ MB = 1024 * 1024
+ CLUSTER = 64 * 1024
+
+ # Runs several COMMIT_BUFFER_SIZE (512K) chunks long, of every kind.
+ SIZE = 32 * MB
+ LAYOUT = [
+ (0, 4 * MB, 'data'),
+ (4 * MB, 6 * MB, 'hole'),
+ (10 * MB, 4 * MB, 'data'),
+ (14 * MB, 6 * MB, 'zero'),
+ (20 * MB, 4 * MB, 'data'),
+ (24 * MB, 8 * MB, 'hole'),
+ ]
+
+ # The same, with every transition off the 512K boundary.
+ SIZE_FRAGMENTED = 384 * CLUSTER # 24M
+ LAYOUT_FRAGMENTED = [
+ (0, 45 * CLUSTER, 'data'),
+ (45 * CLUSTER, 55 * CLUSTER, 'hole'),
+ (100 * CLUSTER, CLUSTER, 'data'),
+ (101 * CLUSTER, 49 * CLUSTER, 'zero'),
+ (150 * CLUSTER, 80 * CLUSTER, 'data'),
+ (230 * CLUSTER, CLUSTER, 'hole'),
+ (231 * CLUSTER, 69 * CLUSTER, 'data'),
+ (300 * CLUSTER, 83 * CLUSTER, 'zero'),
+ (383 * CLUSTER, CLUSTER, 'hole'),
+ ]
+
+ def setUp(self):
+ self.vm = iotests.VM()
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ for img in (backing_img, mid_img, test_img, reference_img):
+ if os.path.exists(img):
+ os.remove(img)
+
+ def build_images(self, layout, size):
+ # A pattern of its own in base, so a misplaced cluster shows up.
+ qemu_img_create('-f', iotests.imgfmt, backing_img, str(size))
+ qemu_io('-c', f'write -P 0x11 0 {size}', backing_img)
+
+ qemu_img_create('-f', iotests.imgfmt, '-b', backing_img, '-F',
+ iotests.imgfmt, mid_img, str(size))
+ for offset, length, kind in layout:
+ if kind == 'data':
+ qemu_io('-c', f'write -P 0x22 {offset} {length}', mid_img)
+ elif kind == 'zero':
+ qemu_io('-c', f'write -z {offset} {length}', mid_img)
+
+ # What base must equal once mid is committed into it.
+ qemu_img('convert', '-f', iotests.imgfmt, '-O', iotests.imgfmt,
+ mid_img, reference_img)
+
+ # An empty layer above mid, so top_node=mid is not the active one.
+ qemu_img_create('-f', iotests.imgfmt, '-b', mid_img, '-F',
+ iotests.imgfmt, test_img, str(size))
+
+ self.vm.cmd('blockdev-add', {
+ 'node-name': 'base',
+ 'driver': iotests.imgfmt,
+ 'file': {'driver': 'file', 'filename': backing_img},
+ })
+ self.vm.cmd('blockdev-add', {
+ 'node-name': 'mid',
+ 'driver': iotests.imgfmt,
+ 'file': {'driver': 'file', 'filename': mid_img},
+ 'backing': 'base',
+ })
+ self.vm.cmd('blockdev-add', {
+ 'node-name': 'active',
+ 'driver': iotests.imgfmt,
+ 'file': {'driver': 'file', 'filename': test_img},
+ 'backing': 'mid',
+ })
+
+ def commit_and_verify(self):
+ self.vm.cmd('block-commit', job_id='commit0', device='active',
+ top_node='mid', base_node='base')
+ self.wait_until_completed(drive='commit0')
+
+ self.vm.cmd('blockdev-del', node_name='active')
+ self.vm.cmd('blockdev-del', node_name='mid')
+ self.vm.cmd('blockdev-del', node_name='base')
+ self.assertTrue(compare_images(reference_img, backing_img))
+
+ def test_commit_large_runs(self):
+ self.build_images(self.LAYOUT, self.SIZE)
+ self.commit_and_verify()
+
+ def test_commit_fragmented_runs(self):
+ self.build_images(self.LAYOUT_FRAGMENTED, self.SIZE_FRAGMENTED)
+ self.commit_and_verify()
+
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'],
supported_protocols=['file'])
diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out
index 1bb1dc5f0ea..d2e2a2d98f6 100644
--- a/tests/qemu-iotests/040.out
+++ b/tests/qemu-iotests/040.out
@@ -1,5 +1,5 @@
-.................................................................
+...................................................................
----------------------------------------------------------------------
-Ran 65 tests
+Ran 67 tests
OK
--
2.53.0
next prev parent reply other threads:[~2026-09-30 11:18 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 11:17 [PATCH hci-8.0 0/9] block: cheaper zero handling in backup and commit #VSTOR-134085 Denis V. Lunev
2026-09-30 11:17 ` [PATCH hci-8.0 1/9] block/commit: pass BDRV_WANT_PRECISE to block-status #VSTOR-134085 Denis V. Lunev
2026-09-30 11:20 ` no-reply
2026-09-30 11:17 ` Denis V. Lunev [this message]
2026-09-30 11:19 ` [PATCH hci-8.0 2/9] iotests/040: cover large and fragmented commit runs #VSTOR-134085 no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 3/9] block/commit: batch block-status queries #VSTOR-134085 Denis V. Lunev
2026-09-30 11:21 ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 4/9] iotests/124: cover backup of zero clusters and holes #VSTOR-134085 Denis V. Lunev
2026-09-30 11:31 ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 5/9] block/block-copy: don't reserve memory for zero tasks #VSTOR-134085 Denis V. Lunev
2026-09-30 11:22 ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 6/9] block/block-copy: extract block_copy_set_task_method() #VSTOR-134085 Denis V. Lunev
2026-09-30 11:22 ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 7/9] block/block-copy: track known-zero source clusters #VSTOR-134085 Denis V. Lunev
2026-09-30 11:30 ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 8/9] block/backup: pre-fill zero_bitmap for full/bitmap #VSTOR-134085 Denis V. Lunev
2026-09-30 11:33 ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 9/9] block/block-copy: coalesce write-zeroes tasks #VSTOR-134085 Denis V. Lunev
2026-09-30 11:34 ` no-reply
2026-09-30 12:49 ` [PATCH hci-8.0 0/9] block: cheaper zero handling in backup and commit #VSTOR-134085 Andrey Drobyshev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260930111739.3866427-3-den@openvz.org \
--to=den@openvz.org \
--cc=andrey.drobyshev@virtuozzo.com \
--cc=den@virtuozzo.com \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox