aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-09-11 14:47:49 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-09-11 14:47:49 +0100
commit2499453eb1cbb68a45d7562a180afd7659007fd4 (patch)
tree71e256143ef313c34e6e00b7bddb1c8e4bb6e5d8 /tests
parent922781b7b37de22a06269f25c9c1ae66293c5991 (diff)
parentb9be6faed1a069526efdc80df7318b16afc6e116 (diff)
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches: - qemu-img create: Fail gracefully when backing file is an empty string - Fixes related to filter block nodes ("Deal with filters" series) - block/nvme: Various cleanups required to use multiple queues - block/nvme: Use NvmeBar structure from "block/nvme.h" - file-win32: Fix "locking" option - iotests: Allow running from different directory # gpg: Signature made Thu 10 Sep 2020 10:11:19 BST # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (65 commits) block/qcow2-cluster: Add missing "fallthrough" annotation block/nvme: Pair doorbell registers block/nvme: Use generic NvmeBar structure block/nvme: Group controller registers in NVMeRegs structure file-win32: Fix "locking" option iotests: Allow running from different directory iotests: Test committing to overridden backing iotests: Add test for commit in sub directory iotests: Add filter mirror test cases iotests: Add filter commit test cases iotests: Let complete_and_wait() work with commit iotests: Test that qcow2's data-file is flushed block: Leave BDS.backing_{file,format} constant block: Inline bdrv_co_block_status_from_*() blockdev: Fix active commit choice block: Drop backing_bs() qemu-img: Use child access functions nbd: Use CAF when looking for dirty bitmap commit: Deal with filters backup: Deal with filters ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rwxr-xr-xtests/qemu-iotests/02044
-rw-r--r--tests/qemu-iotests/020.out10
-rwxr-xr-xtests/qemu-iotests/040238
-rw-r--r--tests/qemu-iotests/040.out4
-rwxr-xr-xtests/qemu-iotests/041146
-rw-r--r--tests/qemu-iotests/041.out4
-rwxr-xr-xtests/qemu-iotests/0494
-rw-r--r--tests/qemu-iotests/049.out5
-rw-r--r--tests/qemu-iotests/153.out2
-rwxr-xr-xtests/qemu-iotests/1843
-rw-r--r--tests/qemu-iotests/184.out14
-rw-r--r--tests/qemu-iotests/204.out1
-rwxr-xr-xtests/qemu-iotests/2286
-rw-r--r--tests/qemu-iotests/228.out6
-rwxr-xr-xtests/qemu-iotests/24449
-rw-r--r--tests/qemu-iotests/244.out7
-rwxr-xr-xtests/qemu-iotests/2454
-rw-r--r--tests/qemu-iotests/273.out4
-rwxr-xr-xtests/qemu-iotests/check2
-rw-r--r--tests/qemu-iotests/iotests.py10
20 files changed, 539 insertions, 24 deletions
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
index a0782937b0..596505be2d 100755
--- a/tests/qemu-iotests/020
+++ b/tests/qemu-iotests/020
@@ -31,6 +31,11 @@ _cleanup()
_cleanup_test_img
_rm_test_img "$TEST_IMG.base"
_rm_test_img "$TEST_IMG.orig"
+
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base"
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.mid"
+ _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT"
+ rmdir "$TEST_DIR/subdir" &> /dev/null
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -139,6 +144,45 @@ $QEMU_IO -c 'writev 0 64k' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG commit "$TEST_IMG"
_cleanup
+
+echo
+echo 'Testing commit in sub-directory with relative filenames'
+echo
+
+pushd "$TEST_DIR" > /dev/null
+
+mkdir subdir
+
+TEST_IMG="subdir/t.$IMGFMT.base" _make_test_img 1M
+TEST_IMG="subdir/t.$IMGFMT.mid" _make_test_img -b "t.$IMGFMT.base" -F $IMGFMT
+TEST_IMG="subdir/t.$IMGFMT" _make_test_img -b "t.$IMGFMT.mid" -F $IMGFMT
+
+# Should work
+$QEMU_IMG commit -b "t.$IMGFMT.mid" "subdir/t.$IMGFMT"
+
+# Might theoretically work, but does not in practice (we have to
+# decide between this and the above; and since we always represent
+# backing file names as relative to the overlay, we go for the above)
+$QEMU_IMG commit -b "subdir/t.$IMGFMT.mid" "subdir/t.$IMGFMT" 2>&1 | \
+ _filter_imgfmt
+
+# This should work as well
+$QEMU_IMG commit -b "$TEST_DIR/subdir/t.$IMGFMT.mid" "subdir/t.$IMGFMT"
+
+popd > /dev/null
+
+# Now let's try with just absolute filenames
+# (This will not work with external data files, though, because when
+# using relative paths for those, qemu will always resolve them
+# relative to its CWD. Therefore, it cannot find those data files now
+# that we left $TEST_DIR.)
+if _get_data_file '' > /dev/null; then
+ echo 'Image committed.' # Skip test
+else
+ $QEMU_IMG commit -b "$TEST_DIR/subdir/t.$IMGFMT.mid" \
+ "$TEST_DIR/subdir/t.$IMGFMT"
+fi
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/020.out b/tests/qemu-iotests/020.out
index 5936bc1cae..a5db1962ad 100644
--- a/tests/qemu-iotests/020.out
+++ b/tests/qemu-iotests/020.out
@@ -1083,4 +1083,14 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=json:{'driv
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-img: Block job failed: No space left on device
+
+Testing commit in sub-directory with relative filenames
+
+Formatting 'subdir/t.IMGFMT.base', fmt=IMGFMT size=1048576
+Formatting 'subdir/t.IMGFMT.mid', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.base backing_fmt=IMGFMT
+Formatting 'subdir/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=t.IMGFMT.mid backing_fmt=IMGFMT
+Image committed.
+qemu-img: Did not find 'subdir/t.IMGFMT.mid' in the backing chain of 'subdir/t.IMGFMT'
+Image committed.
+Image committed.
*** done
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index f58f50d023..caf286571a 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -734,6 +734,244 @@ class TestErrorHandling(iotests.QMPTestCase):
self.assertTrue(iotests.compare_images(mid_img, backing_img, fmt2='raw'),
'target image does not match source after commit')
+class TestCommitWithFilters(iotests.QMPTestCase):
+ img0 = os.path.join(iotests.test_dir, '0.img')
+ img1 = os.path.join(iotests.test_dir, '1.img')
+ img2 = os.path.join(iotests.test_dir, '2.img')
+ img3 = os.path.join(iotests.test_dir, '3.img')
+
+ def do_test_io(self, read_or_write):
+ for index, pattern_file in enumerate(self.pattern_files):
+ result = qemu_io('-f', iotests.imgfmt,
+ '-c',
+ f'{read_or_write} -P {index + 1} {index}M 1M',
+ pattern_file)
+ self.assertFalse('Pattern verification failed' in result)
+
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, self.img0, '64M')
+ qemu_img('create', '-f', iotests.imgfmt, self.img1, '64M')
+ qemu_img('create', '-f', iotests.imgfmt, self.img2, '64M')
+ qemu_img('create', '-f', iotests.imgfmt, self.img3, '64M')
+
+ # Distributions of the patterns in the files; this is checked
+ # by tearDown() and should be changed by the test cases as is
+ # necessary
+ self.pattern_files = [self.img0, self.img1, self.img2, self.img3]
+
+ self.do_test_io('write')
+
+ self.vm = iotests.VM().add_device('virtio-scsi,id=vio-scsi')
+ self.vm.launch()
+
+ result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('blockdev-add', **{
+ 'node-name': 'top-filter',
+ 'driver': 'throttle',
+ 'throttle-group': 'tg',
+ 'file': {
+ 'node-name': 'cow-3',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': self.img3
+ },
+ 'backing': {
+ 'node-name': 'cow-2',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': self.img2
+ },
+ 'backing': {
+ 'node-name': 'cow-1',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': self.img1
+ },
+ 'backing': {
+ 'node-name': 'bottom-filter',
+ 'driver': 'throttle',
+ 'throttle-group': 'tg',
+ 'file': {
+ 'node-name': 'cow-0',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': self.img0
+ }
+ }
+ }
+ }
+ }
+ }
+ })
+ self.assert_qmp(result, 'return', {})
+
+ def tearDown(self):
+ self.vm.shutdown()
+ self.do_test_io('read')
+
+ os.remove(self.img3)
+ os.remove(self.img2)
+ os.remove(self.img1)
+ os.remove(self.img0)
+
+ # Filters make for funny filenames, so we cannot just use
+ # self.imgX to get them
+ def get_filename(self, node):
+ return self.vm.node_info(node)['image']['filename']
+
+ def test_filterless_commit(self):
+ result = self.vm.qmp('block-commit',
+ job_id='commit',
+ device='top-filter',
+ top_node='cow-2',
+ base_node='cow-1')
+ self.assert_qmp(result, 'return', {})
+ self.wait_until_completed(drive='commit')
+
+ self.assertIsNotNone(self.vm.node_info('cow-3'))
+ self.assertIsNone(self.vm.node_info('cow-2'))
+ self.assertIsNotNone(self.vm.node_info('cow-1'))
+
+ # 2 has been comitted into 1
+ self.pattern_files[2] = self.img1
+
+ def test_commit_through_filter(self):
+ result = self.vm.qmp('block-commit',
+ job_id='commit',
+ device='top-filter',
+ top_node='cow-1',
+ base_node='cow-0')
+ self.assert_qmp(result, 'return', {})
+ self.wait_until_completed(drive='commit')
+
+ self.assertIsNotNone(self.vm.node_info('cow-2'))
+ self.assertIsNone(self.vm.node_info('cow-1'))
+ self.assertIsNone(self.vm.node_info('bottom-filter'))
+ self.assertIsNotNone(self.vm.node_info('cow-0'))
+
+ # 1 has been comitted into 0
+ self.pattern_files[1] = self.img0
+
+ def test_filtered_active_commit_with_filter(self):
+ # Add a device, so the commit job finds a parent it can change
+ # to point to the base node (so we can test that top-filter is
+ # dropped from the graph)
+ result = self.vm.qmp('device_add', id='drv0', driver='scsi-hd',
+ bus='vio-scsi.0', drive='top-filter')
+ self.assert_qmp(result, 'return', {})
+
+ # Try to release our reference to top-filter; that should not
+ # work because drv0 uses it
+ result = self.vm.qmp('blockdev-del', node_name='top-filter')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+ self.assert_qmp(result, 'error/desc', 'Node top-filter is in use')
+
+ result = self.vm.qmp('block-commit',
+ job_id='commit',
+ device='top-filter',
+ base_node='cow-2')
+ self.assert_qmp(result, 'return', {})
+ self.complete_and_wait(drive='commit')
+
+ # Try to release our reference to top-filter again
+ result = self.vm.qmp('blockdev-del', node_name='top-filter')
+ self.assert_qmp(result, 'return', {})
+
+ self.assertIsNone(self.vm.node_info('top-filter'))
+ self.assertIsNone(self.vm.node_info('cow-3'))
+ self.assertIsNotNone(self.vm.node_info('cow-2'))
+
+ # Check that drv0 is now connected to cow-2
+ blockdevs = self.vm.qmp('query-block')['return']
+ drv0 = next(dev for dev in blockdevs if dev['qdev'] == 'drv0')
+ self.assertEqual(drv0['inserted']['node-name'], 'cow-2')
+
+ # 3 has been comitted into 2
+ self.pattern_files[3] = self.img2
+
+ def test_filtered_active_commit_without_filter(self):
+ result = self.vm.qmp('block-commit',
+ job_id='commit',
+ device='top-filter',
+ top_node='cow-3',
+ base_node='cow-2')
+ self.assert_qmp(result, 'return', {})
+ self.complete_and_wait(drive='commit')
+
+ self.assertIsNotNone(self.vm.node_info('top-filter'))
+ self.assertIsNone(self.vm.node_info('cow-3'))
+ self.assertIsNotNone(self.vm.node_info('cow-2'))
+
+ # 3 has been comitted into 2
+ self.pattern_files[3] = self.img2
+
+class TestCommitWithOverriddenBacking(iotests.QMPTestCase):
+ img_base_a = os.path.join(iotests.test_dir, 'base_a.img')
+ img_base_b = os.path.join(iotests.test_dir, 'base_b.img')
+ img_top = os.path.join(iotests.test_dir, 'top.img')
+
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, self.img_base_a, '1M')
+ qemu_img('create', '-f', iotests.imgfmt, self.img_base_b, '1M')
+ qemu_img('create', '-f', iotests.imgfmt, '-b', self.img_base_a, \
+ self.img_top)
+
+ self.vm = iotests.VM()
+ self.vm.launch()
+
+ # Use base_b instead of base_a as the backing of top
+ result = self.vm.qmp('blockdev-add', **{
+ 'node-name': 'top',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': self.img_top
+ },
+ 'backing': {
+ 'node-name': 'base',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': self.img_base_b
+ }
+ }
+ })
+ self.assert_qmp(result, 'return', {})
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(self.img_top)
+ os.remove(self.img_base_a)
+ os.remove(self.img_base_b)
+
+ def test_commit_to_a(self):
+ # Try committing to base_a (which should fail, as top's
+ # backing image is base_b instead)
+ result = self.vm.qmp('block-commit',
+ job_id='commit',
+ device='top',
+ base=self.img_base_a)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ def test_commit_to_b(self):
+ # Try committing to base_b (which should work, since that is
+ # actually top's backing image)
+ result = self.vm.qmp('block-commit',
+ job_id='commit',
+ device='top',
+ base=self.img_base_b)
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.event_wait('BLOCK_JOB_READY')
+ self.vm.qmp('block-job-complete', device='commit')
+ self.vm.event_wait('BLOCK_JOB_COMPLETED')
+
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 6a917130b6..1bb1dc5f0e 100644
--- a/tests/qemu-iotests/040.out
+++ b/tests/qemu-iotests/040.out
@@ -1,5 +1,5 @@
-...........................................................
+.................................................................
----------------------------------------------------------------------
-Ran 59 tests
+Ran 65 tests
OK
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index f0a7bf6650..a7780853cd 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -21,8 +21,9 @@
import time
import os
import re
+import json
import iotests
-from iotests import qemu_img, qemu_io
+from iotests import qemu_img, qemu_img_pipe, qemu_io
backing_img = os.path.join(iotests.test_dir, 'backing.img')
target_backing_img = os.path.join(iotests.test_dir, 'target-backing.img')
@@ -1288,6 +1289,149 @@ class TestReplaces(iotests.QMPTestCase):
self.vm.assert_block_path('filter0', '/file', 'target')
+# Tests for mirror with filters (and how the mirror filter behaves, as
+# an example for an implicit filter)
+class TestFilters(iotests.QMPTestCase):
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, backing_img, '1M')
+ qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, test_img)
+ qemu_img('create', '-f', iotests.imgfmt, '-b', backing_img, target_img)
+
+ qemu_io('-c', 'write -P 1 0 512k', backing_img)
+ qemu_io('-c', 'write -P 2 512k 512k', test_img)
+
+ self.vm = iotests.VM().add_device('virtio-scsi,id=vio-scsi')
+ self.vm.launch()
+
+ result = self.vm.qmp('blockdev-add', **{
+ 'node-name': 'target',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': target_img
+ },
+ 'backing': None
+ })
+ self.assert_qmp(result, 'return', {})
+
+ self.filterless_chain = {
+ 'node-name': 'source',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': test_img
+ },
+ 'backing': {
+ 'node-name': 'backing',
+ 'driver': iotests.imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': backing_img
+ }
+ }
+ }
+
+ def tearDown(self):
+ self.vm.shutdown()
+
+ os.remove(test_img)
+ os.remove(target_img)
+ os.remove(backing_img)
+
+ def test_cor(self):
+ result = self.vm.qmp('blockdev-add', **{
+ 'node-name': 'filter',
+ 'driver': 'copy-on-read',
+ 'file': self.filterless_chain
+ })
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('blockdev-mirror',
+ job_id='mirror',
+ device='filter',
+ target='target',
+ sync='top')
+ self.assert_qmp(result, 'return', {})
+
+ self.complete_and_wait('mirror')
+
+ self.vm.qmp('blockdev-del', node_name='target')
+
+ target_map = qemu_img_pipe('map', '--output=json', target_img)
+ target_map = json.loads(target_map)
+
+ assert target_map[0]['start'] == 0
+ assert target_map[0]['length'] == 512 * 1024
+ assert target_map[0]['depth'] == 1
+
+ assert target_map[1]['start'] == 512 * 1024
+ assert target_map[1]['length'] == 512 * 1024
+ assert target_map[1]['depth'] == 0
+
+ def test_implicit_mirror_filter(self):
+ result = self.vm.qmp('blockdev-add', **self.filterless_chain)
+ self.assert_qmp(result, 'return', {})
+
+ # We need this so we can query from above the mirror node
+ result = self.vm.qmp('device_add',
+ driver='scsi-hd',
+ id='virtio',
+ bus='vio-scsi.0',
+ drive='source')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('blockdev-mirror',
+ job_id='mirror',
+ device='source',
+ target='target',
+ sync='top')
+ self.assert_qmp(result, 'return', {})
+
+ # The mirror filter is now an implicit node, so it should be
+ # invisible when querying the backing chain
+ blockdevs = self.vm.qmp('query-block')['return']
+ device_info = next(dev for dev in blockdevs if dev['qdev'] == 'virtio')
+
+ assert device_info['inserted']['node-name'] == 'source'
+
+ image_info = device_info['inserted']['image']
+ assert image_info['filename'] == test_img
+ assert image_info['backing-image']['filename'] == backing_img
+
+ self.complete_and_wait('mirror')
+
+ def test_explicit_mirror_filter(self):
+ # Same test as above, but this time we give the mirror filter
+ # a node-name so it will not be invisible
+ result = self.vm.qmp('blockdev-add', **self.filterless_chain)
+ self.assert_qmp(result, 'return', {})
+
+ # We need this so we can query from above the mirror node
+ result = self.vm.qmp('device_add',
+ driver='scsi-hd',
+ id='virtio',
+ bus='vio-scsi.0',
+ drive='source')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('blockdev-mirror',
+ job_id='mirror',
+ device='source',
+ target='target',
+ sync='top',
+ filter_node_name='mirror-filter')
+ self.assert_qmp(result, 'return', {})
+
+ # With a node-name given to it, the mirror filter should now
+ # be visible
+ blockdevs = self.vm.qmp('query-block')['return']
+ device_info = next(dev for dev in blockdevs if dev['qdev'] == 'virtio')
+
+ assert device_info['inserted']['node-name'] == 'mirror-filter'
+
+ self.complete_and_wait('mirror')
+
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'],
supported_protocols=['file'],
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 53abe11d73..46651953e8 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-........................................................................................................
+...........................................................................................................
----------------------------------------------------------------------
-Ran 104 tests
+Ran 107 tests
OK
diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049
index 051a1c79e0..82b1e6c202 100755
--- a/tests/qemu-iotests/049
+++ b/tests/qemu-iotests/049
@@ -119,6 +119,10 @@ test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=on "$TEST_IMG" 64M
test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=off "$TEST_IMG" 64M
test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=on "$TEST_IMG" 64M
+echo "== Expect error when backing file name is empty string =="
+echo
+test_qemu_img create -f $IMGFMT -b '' $TEST_IMG 1M
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index a7e220830d..b1d8fd9107 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -209,4 +209,9 @@ qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16
qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
+== Expect error when backing file name is empty string ==
+
+qemu-img create -f qcow2 -b TEST_DIR/t.qcow2 1M
+qemu-img: TEST_DIR/t.qcow2: Expected backing file name, got empty string
+
*** done
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
index 8a79e1ee87..fcaa71aeee 100644
--- a/tests/qemu-iotests/153.out
+++ b/tests/qemu-iotests/153.out
@@ -464,7 +464,7 @@ No conflict:
image: null-co://
file format: null-co
virtual size: 1 GiB (1073741824 bytes)
-disk size: unavailable
+disk size: 0 B
Conflict:
qemu-img: --force-share/-U conflicts with image options
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
index 33dd8d2a4f..eebb53faed 100755
--- a/tests/qemu-iotests/184
+++ b/tests/qemu-iotests/184
@@ -45,8 +45,7 @@ do_run_qemu()
run_qemu()
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
- | _filter_qemu_io | _filter_generated_node_ids \
- | _filter_actual_image_size
+ | _filter_qemu_io | _filter_generated_node_ids
}
test_throttle=$($QEMU_IMG --help|grep throttle)
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
index 3deb3cfb94..87c73070e3 100644
--- a/tests/qemu-iotests/184.out
+++ b/tests/qemu-iotests/184.out
@@ -27,14 +27,21 @@ Testing:
"iops_rd": 0,
"detect_zeroes": "off",
"image": {
+ "backing-image": {
+ "virtual-size": 1073741824,
+ "filename": "null-co://",
+ "format": "null-co",
+ "actual-size": 0
+ },
"virtual-size": 1073741824,
"filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"null-co\"}}",
- "format": "throttle"
+ "format": "throttle",
+ "actual-size": 0
},
"iops_wr": 0,
"ro": false,
"node-name": "throttle0",
- "backing_file_depth": 0,
+ "backing_file_depth": 1,
"drv": "throttle",
"iops": 0,
"bps_wr": 0,
@@ -56,7 +63,8 @@ Testing:
"image": {
"virtual-size": 1073741824,
"filename": "null-co://",
- "format": "null-co"
+ "format": "null-co",
+ "actual-size": 0
},
"iops_wr": 0,
"ro": false,
diff --git a/tests/qemu-iotests/204.out b/tests/qemu-iotests/204.out
index 457f72df8f..4d903d20ea 100644
--- a/tests/qemu-iotests/204.out
+++ b/tests/qemu-iotests/204.out
@@ -59,5 +59,6 @@ Offset Length File
0x900000 0x2400000 TEST_DIR/t.IMGFMT
0x3c00000 0x1100000 TEST_DIR/t.IMGFMT
0x6a00000 0x400000 TEST_DIR/t.IMGFMT
+0x6e00000 0x1200000 TEST_DIR/t.IMGFMT.base
No errors were found on the image.
*** done
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
index 60db986d84..266fce6cda 100755
--- a/tests/qemu-iotests/228
+++ b/tests/qemu-iotests/228
@@ -36,7 +36,7 @@ def log_node_info(node):
log('bs->filename: ' + node['image']['filename'],
filters=[filter_testfiles, filter_imgfmt])
- log('bs->backing_file: ' + node['backing_file'],
+ log('bs->backing_file: ' + node['image']['full-backing-filename'],
filters=[filter_testfiles, filter_imgfmt])
if 'backing-image' in node['image']:
@@ -73,8 +73,8 @@ with iotests.FilePath('base.img') as base_img_path, \
},
filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
- # Filename should be plain, and the backing filename should not
- # contain the "file:" prefix
+ # Filename should be plain, and the backing node filename should
+ # not contain the "file:" prefix
log_node_info(vm.node_info('node0'))
vm.qmp_log('blockdev-del', node_name='node0')
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
index 4217df24fe..8c82009abe 100644
--- a/tests/qemu-iotests/228.out
+++ b/tests/qemu-iotests/228.out
@@ -4,7 +4,7 @@
{"return": {}}
bs->filename: TEST_DIR/PID-top.img
-bs->backing_file: TEST_DIR/PID-base.img
+bs->backing_file: file:TEST_DIR/PID-base.img
bs->backing->bs->filename: TEST_DIR/PID-base.img
{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
@@ -41,7 +41,7 @@ bs->backing->bs->filename: TEST_DIR/PID-base.img
{"return": {}}
bs->filename: TEST_DIR/PID-top.img
-bs->backing_file: TEST_DIR/PID-base.img
+bs->backing_file: file:TEST_DIR/PID-base.img
bs->backing->bs->filename: TEST_DIR/PID-base.img
{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
@@ -55,7 +55,7 @@ bs->backing->bs->filename: TEST_DIR/PID-base.img
{"return": {}}
bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
-bs->backing_file: null-co://
+bs->backing_file: TEST_DIR/PID-base.img
bs->backing->bs->filename: null-co://
{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
index efe3c0428b..f2b2dddf1c 100755
--- a/tests/qemu-iotests/244
+++ b/tests/qemu-iotests/244
@@ -217,6 +217,55 @@ $QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG"
$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
+echo
+echo "=== Flushing should flush the data file ==="
+echo
+
+# We are going to flush a qcow2 file with a blkdebug node inserted
+# between the qcow2 node and its data file node. The blkdebug node
+# will return an error for all flushes and so we if the data file is
+# flushed, we will see qemu-io return an error.
+
+# We need to write something or the flush will not do anything; we
+# also need -t writeback so the write is not done as a FUA write
+# (which would then fail thanks to the implicit flush)
+$QEMU_IO -c 'write 0 512' -c flush \
+ -t writeback \
+ "json:{
+ 'driver': 'qcow2',
+ 'file': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG'
+ },
+ 'data-file': {
+ 'driver': 'blkdebug',
+ 'inject-error': [{
+ 'event': 'none',
+ 'iotype': 'flush'
+ }],
+ 'image': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG.data'
+ }
+ }
+ }" \
+ | _filter_qemu_io
+
+result=${PIPESTATUS[0]}
+echo
+
+case $result in
+ 0)
+ echo "ERROR: qemu-io succeeded, so the data file was not flushed"
+ ;;
+ 1)
+ echo "Success: qemu-io failed, so the data file was flushed"
+ ;;
+ *)
+ echo "ERROR: qemu-io returned unknown exit code $result"
+ ;;
+esac
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
index dbab7359a9..7269b4295a 100644
--- a/tests/qemu-iotests/244.out
+++ b/tests/qemu-iotests/244.out
@@ -131,4 +131,11 @@ Offset Length Mapped to File
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
Images are identical.
Images are identical.
+
+=== Flushing should flush the data file ===
+
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+Success: qemu-io failed, so the data file was flushed
*** done
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
index ad91a6f5b4..e60c8326d3 100755
--- a/tests/qemu-iotests/245
+++ b/tests/qemu-iotests/245
@@ -725,7 +725,9 @@ class TestBlockdevReopen(iotests.QMPTestCase):
# Detach hd2 from hd0.
self.reopen(opts, {'backing': None})
- self.reopen(opts, {}, "backing is missing for 'hd0'")
+
+ # Without a backing file, we can omit 'backing' again
+ self.reopen(opts)
# Remove both hd0 and hd2
result = self.vm.qmp('blockdev-del', conv_keys = True, node_name = 'hd0')
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index 87d4758503..8247cbaea1 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -32,7 +32,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"actual-size": SIZE,
"dirty-flag": false
},
- "backing-filename-format": "file",
+ "backing-filename-format": "IMGFMT",
"virtual-size": 67108864,
"filename": "TEST_DIR/t.IMGFMT.mid",
"cluster-size": 65536,
@@ -112,7 +112,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
"actual-size": SIZE,
"dirty-flag": false
},
- "backing-filename-format": "file",
+ "backing-filename-format": "IMGFMT",
"virtual-size": 67108864,
"filename": "TEST_DIR/t.IMGFMT.mid",
"cluster-size": 65536,
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 3ab859ac1a..e14a1f354d 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -44,7 +44,7 @@ then
_init_error "failed to obtain source tree name from check symlink"
fi
source_iotests=$(cd "$source_iotests"; pwd) || _init_error "failed to enter source tree"
- build_iotests=$PWD
+ build_iotests=$(readlink -f $(dirname "$0"))
else
# called from the source tree
source_iotests=$PWD
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index e197c73ca5..64ccaf9061 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -972,8 +972,12 @@ class QMPTestCase(unittest.TestCase):
def wait_ready(self, drive='drive0'):
"""Wait until a BLOCK_JOB_READY event, and return the event."""
- f = {'data': {'type': 'mirror', 'device': drive}}
- return self.vm.event_wait(name='BLOCK_JOB_READY', match=f)
+ return self.vm.events_wait([
+ ('BLOCK_JOB_READY',
+ {'data': {'type': 'mirror', 'device': drive}}),
+ ('BLOCK_JOB_READY',
+ {'data': {'type': 'commit', 'device': drive}})
+ ])
def wait_ready_and_cancel(self, drive='drive0'):
self.wait_ready(drive=drive)
@@ -992,7 +996,7 @@ class QMPTestCase(unittest.TestCase):
self.assert_qmp(result, 'return', {})
event = self.wait_until_completed(drive=drive, error=completion_error)
- self.assert_qmp(event, 'data/type', 'mirror')
+ self.assertTrue(event['data']['type'] in ['mirror', 'commit'])
def pause_wait(self, job_id='job0'):
with Timeout(3, "Timeout waiting for job to pause"):