diff --git a/block/parallels.c b/block/parallels.c index 2b6c6e570938d12f838024e541a0c97d5fd44e94..9545761f496e67c999d231fad5fb6737bdb38d09 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -35,6 +35,7 @@ #include "qemu/module.h" #include "qemu/bswap.h" #include "qemu/bitmap.h" +#include "migration/blocker.h" /**************************************************************/ @@ -100,6 +101,7 @@ typedef struct BDRVParallelsState { unsigned int tracks; unsigned int off_multiplier; + Error *migration_blocker; } BDRVParallelsState; @@ -708,7 +710,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE; } - if (flags & BDRV_O_RDWR) { + if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_INACTIVE)) { s->header->inuse = cpu_to_le32(HEADER_INUSE_MAGIC); ret = parallels_update_header(bs); if (ret < 0) { @@ -720,6 +722,16 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags, s->bat_dirty_bmap = bitmap_new(DIV_ROUND_UP(s->header_size, s->bat_dirty_block)); + /* Disable migration until bdrv_invalidate_cache method is added */ + error_setg(&s->migration_blocker, "The Parallels format used by node '%s' " + "does not support live migration", + bdrv_get_device_or_node_name(bs)); + ret = migrate_add_blocker(s->migration_blocker, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_free(s->migration_blocker); + goto fail; + } qemu_co_mutex_init(&s->lock); return 0; @@ -741,18 +753,18 @@ static void parallels_close(BlockDriverState *bs) { BDRVParallelsState *s = bs->opaque; - if (bs->open_flags & BDRV_O_RDWR) { + if ((bs->open_flags & BDRV_O_RDWR) && !(bs->open_flags & BDRV_O_INACTIVE)) { s->header->inuse = 0; parallels_update_header(bs); - } - - if (bs->open_flags & BDRV_O_RDWR) { bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, PREALLOC_MODE_OFF, NULL); } g_free(s->bat_dirty_bmap); qemu_vfree(s->header); + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static QemuOptsList parallels_create_opts = { diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index fb10e2606817f699ed4dbf34bed37d2efefa3cca..2e072ed155601f79d1e3507476222ad867d80af3 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -278,6 +278,14 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) goto fail; } + /* If we're allocating the table at offset 0 then something is wrong */ + if (l2_offset == 0) { + qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid " + "allocation of L2 table at offset 0"); + ret = -EIO; + goto fail; + } + ret = qcow2_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { goto fail; diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index aa3fd6cf17d0b0de1b44954f50606a974134fdc2..60b8eef3e8befd2467a41d865779f3a567f66f68 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -367,6 +367,13 @@ static int alloc_refcount_block(BlockDriverState *bs, return new_block; } + /* If we're allocating the block at offset 0 then something is wrong */ + if (new_block == 0) { + qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid " + "allocation of refcount block at offset 0"); + return -EIO; + } + #ifdef DEBUG_ALLOC2 fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64 " at %" PRIx64 "\n", @@ -1075,6 +1082,13 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) return new_cluster; } + if (new_cluster == 0) { + qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid " + "allocation of compressed cluster " + "at offset 0"); + return -EIO; + } + if (!offset || ROUND_UP(offset, s->cluster_size) != new_cluster) { offset = new_cluster; free_in_cluster = s->cluster_size; diff --git a/block/qcow2.c b/block/qcow2.c index 92cb9f9bfa2e090d1b9508e0f09df942b43fdaef..b3d66a0e88c675c0ab971d5c6723a8e3672b3d47 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -126,6 +126,7 @@ static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen, /* Zero fill remaining space in cluster so it has predictable * content in case of future spec changes */ clusterlen = size_to_clusters(s, headerlen) * s->cluster_size; + assert(qcow2_pre_write_overlap_check(bs, 0, ret, clusterlen) == 0); ret = bdrv_pwrite_zeroes(bs->file, ret + headerlen, clusterlen - headerlen, 0); @@ -1280,6 +1281,12 @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } + if (header.refcount_table_clusters == 0 && !(flags & BDRV_O_CHECK)) { + error_setg(errp, "Image does not contain a reference count table"); + ret = -EINVAL; + goto fail; + } + ret = validate_table_offset(bs, s->refcount_table_offset, s->refcount_table_size, sizeof(uint64_t)); if (ret < 0) { diff --git a/block/snapshot.c b/block/snapshot.c index a46564e7b7da7ce9dd5cabe1838025777165dc07..1d5ab5f90f6c354f2f2604376339ec9c9c9143fc 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -181,10 +181,24 @@ int bdrv_snapshot_goto(BlockDriverState *bs, { BlockDriver *drv = bs->drv; int ret, open_ret; + int64_t len; if (!drv) { return -ENOMEDIUM; } + + len = bdrv_getlength(bs); + if (len < 0) { + return len; + } + /* We should set all bits in all enabled dirty bitmaps, because dirty + * bitmaps reflect active state of disk and snapshot switch operation + * actually dirties active state. + * TODO: It may make sense not to set all bits but analyze block status of + * current state and destination snapshot and do not set bits corresponding + * to both-zero or both-unallocated areas. */ + bdrv_set_dirty(bs, 0, len); + if (drv->bdrv_snapshot_goto) { return drv->bdrv_snapshot_goto(bs, snapshot_id); } diff --git a/block/vhdx.c b/block/vhdx.c index 7ae4589879bc7d621e44ddefa206e64004de2f6c..9956933da60c6e0c1c2ba5ebd1e09d0bc6096c0a 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1008,13 +1008,6 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } - if (flags & BDRV_O_RDWR) { - ret = vhdx_update_headers(bs, s, false, NULL); - if (ret < 0) { - goto fail; - } - } - /* TODO: differencing files */ return 0; diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 18838948faeccdc3dbc99f2557d0fb4a0e211616..457984b8e9c7f30d7cc59b9f226b0f8e143063ab 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -666,6 +666,7 @@ class TestENOSPC(TestErrors): if event['event'] == 'BLOCK_JOB_ERROR': self.assert_qmp(event, 'data/device', 'drive0') self.assert_qmp(event, 'data/operation', 'read') + error = True result = self.vm.qmp('query-block-jobs') self.assert_qmp(result, 'return[0]/paused', True) @@ -676,9 +677,11 @@ class TestENOSPC(TestErrors): self.assert_qmp(result, 'return', {}) result = self.vm.qmp('query-block-jobs') + if result == {'return': []}: + # Race; likely already finished. Check. + continue self.assert_qmp(result, 'return[0]/paused', False) self.assert_qmp(result, 'return[0]/io-status', 'ok') - error = True elif event['event'] == 'BLOCK_JOB_COMPLETED': self.assertTrue(error, 'job completed unexpectedly') self.assert_qmp(event, 'data/type', 'stream') @@ -792,13 +795,14 @@ class TestSetSpeed(iotests.QMPTestCase): self.assert_no_active_block_jobs() + self.vm.pause_drive('drive0') result = self.vm.qmp('block-stream', device='drive0') self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) self.assert_qmp(result, 'error/class', 'GenericError') - self.cancel_and_wait() + self.cancel_and_wait(resume=True) if __name__ == '__main__': iotests.main(supported_fmts=['qcow2', 'qed']) diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index c284d08796c9ad9a2da5bfac6d2bffdeb3872f50..90b5b4f2adb03dc362ca8da0572ecde9b77b6e5f 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -289,7 +289,7 @@ class TestSetSpeed(ImageCommitTestCase): qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 0 512', test_img) qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img) - self.vm = iotests.VM().add_drive(test_img) + self.vm = iotests.VM().add_drive('blkdebug::' + test_img) self.vm.launch() def tearDown(self): diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 index e1206caf9b636815a6e0db0061d02f7c3d2a30b0..8a5d9fd26913c0d7aeb9da19742506c0a0865c03 100755 --- a/tests/qemu-iotests/055 +++ b/tests/qemu-iotests/055 @@ -48,7 +48,7 @@ class TestSingleDrive(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) - self.vm = iotests.VM().add_drive(test_img) + self.vm = iotests.VM().add_drive('blkdebug::' + test_img) self.vm.add_drive(blockdev_target_img, interface="none") if iotests.qemu_default_machine == 'pc': self.vm.add_drive(None, 'media=cdrom', 'ide') @@ -65,10 +65,11 @@ class TestSingleDrive(iotests.QMPTestCase): def do_test_cancel(self, cmd, target): self.assert_no_active_block_jobs() + self.vm.pause_drive('drive0') result = self.vm.qmp(cmd, device='drive0', target=target, sync='full') self.assert_qmp(result, 'return', {}) - event = self.cancel_and_wait() + event = self.cancel_and_wait(resume=True) self.assert_qmp(event, 'data/type', 'backup') def test_cancel_drive_backup(self): @@ -166,7 +167,7 @@ class TestSetSpeed(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) - self.vm = iotests.VM().add_drive(test_img) + self.vm = iotests.VM().add_drive('blkdebug::' + test_img) self.vm.add_drive(blockdev_target_img, interface="none") self.vm.launch() @@ -246,6 +247,8 @@ class TestSetSpeed(iotests.QMPTestCase): def test_set_speed_invalid_blockdev_backup(self): self.do_test_set_speed_invalid('blockdev-backup', 'drive1') +# Note: We cannot use pause_drive() here, or the transaction command +# would stall. Instead, we limit the block job speed here. class TestSingleTransaction(iotests.QMPTestCase): def setUp(self): qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(image_len)) @@ -271,7 +274,8 @@ class TestSingleTransaction(iotests.QMPTestCase): 'type': cmd, 'data': { 'device': 'drive0', 'target': target, - 'sync': 'full' }, + 'sync': 'full', + 'speed': 64 * 1024 }, } ]) @@ -289,12 +293,12 @@ class TestSingleTransaction(iotests.QMPTestCase): def do_test_pause(self, cmd, target, image): self.assert_no_active_block_jobs() - self.vm.pause_drive('drive0') result = self.vm.qmp('transaction', actions=[{ 'type': cmd, 'data': { 'device': 'drive0', 'target': target, - 'sync': 'full' }, + 'sync': 'full', + 'speed': 64 * 1024 }, } ]) self.assert_qmp(result, 'return', {}) @@ -302,7 +306,9 @@ class TestSingleTransaction(iotests.QMPTestCase): result = self.vm.qmp('block-job-pause', device='drive0') self.assert_qmp(result, 'return', {}) - self.vm.resume_drive('drive0') + result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0) + self.assert_qmp(result, 'return', {}) + self.pause_job('drive0') result = self.vm.qmp('query-block-jobs') @@ -461,7 +467,7 @@ class TestDriveCompression(iotests.QMPTestCase): pass def do_prepare_drives(self, fmt, args, attach_target): - self.vm = iotests.VM().add_drive(test_img) + self.vm = iotests.VM().add_drive('blkdebug::' + test_img) qemu_img('create', '-f', fmt, blockdev_target_img, str(TestDriveCompression.image_len), *args) @@ -500,10 +506,11 @@ class TestDriveCompression(iotests.QMPTestCase): self.assert_no_active_block_jobs() + self.vm.pause_drive('drive0') result = self.vm.qmp(cmd, device='drive0', sync='full', compress=True, **args) self.assert_qmp(result, 'return', {}) - event = self.cancel_and_wait() + event = self.cancel_and_wait(resume=True) self.assert_qmp(event, 'data/type', 'backup') self.vm.shutdown() diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 index 8e95c450eb2d30a375658fc7c7bc8485286c9948..fae08b03bfed26b518a7689323c071cad661af71 100755 --- a/tests/qemu-iotests/060 +++ b/tests/qemu-iotests/060 @@ -242,6 +242,65 @@ poke_file "$TEST_IMG" "$(($l2_offset+8))" "\x80\x00\x00\x00\x00\x06\x2a\x00" # Should emit two error messages $QEMU_IO -c "discard 0 64k" -c "read 64k 64k" "$TEST_IMG" | _filter_qemu_io +echo +echo "=== Testing empty refcount table ===" +echo +_make_test_img 64M +poke_file "$TEST_IMG" "$rt_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" +$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io +# Repair the image +_check_test_img -r all + +echo +echo "=== Testing empty refcount table with valid L1 and L2 tables ===" +echo +_make_test_img 64M +$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io +poke_file "$TEST_IMG" "$rt_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" +# Since the first data cluster is already allocated this triggers an +# allocation with an explicit offset (using qcow2_alloc_clusters_at()) +# causing a refcount block to be allocated at offset 0 +$QEMU_IO -c "write 0 128k" "$TEST_IMG" | _filter_qemu_io +# Repair the image +_check_test_img -r all + +echo +echo "=== Testing empty refcount block ===" +echo +_make_test_img 64M +poke_file "$TEST_IMG" "$rb_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" +$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io +# Repair the image +_check_test_img -r all + +echo +echo "=== Testing empty refcount block with compressed write ===" +echo +_make_test_img 64M +$QEMU_IO -c "write 64k 64k" "$TEST_IMG" | _filter_qemu_io +poke_file "$TEST_IMG" "$rb_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" +# The previous write already allocated an L2 table, so now this new +# write will try to allocate a compressed data cluster at offset 0. +$QEMU_IO -c "write -c 0k 64k" "$TEST_IMG" | _filter_qemu_io +# Repair the image +_check_test_img -r all + +echo +echo "=== Testing zero refcount table size ===" +echo +_make_test_img 64M +poke_file "$TEST_IMG" "56" "\x00\x00\x00\x00" +$QEMU_IO -c "write 0 64k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt +# Repair the image +_check_test_img -r all + +echo +echo "=== Testing incorrect refcount table offset ===" +echo +_make_test_img 64M +poke_file "$TEST_IMG" "48" "\x00\x00\x00\x00\x00\x00\x00\x00" +$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index 5ca3af491f65c1b97adc0bb313583c1b8b85f1ec..62c22701b8ec18096178429093c338fee45e51e4 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -181,4 +181,107 @@ qcow2: Marking image as corrupt: Cluster allocation offset 0x62a00 unaligned (L2 discard 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read failed: Input/output error + +=== Testing empty refcount table === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount table); further corruption events will be suppressed +write failed: Input/output error +ERROR cluster 0 refcount=0 reference=1 +ERROR cluster 1 refcount=0 reference=1 +ERROR cluster 3 refcount=0 reference=1 +Rebuilding refcount structure +Repairing cluster 1 refcount=1 reference=0 +The following inconsistencies were found and repaired: + + 0 leaked clusters + 3 corruptions + +Double checking the fixed image now... +No errors were found on the image. + +=== Testing empty refcount table with valid L1 and L2 tables === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qcow2: Marking image as corrupt: Preventing invalid allocation of refcount block at offset 0; further corruption events will be suppressed +write failed: Input/output error +ERROR cluster 0 refcount=0 reference=1 +ERROR cluster 1 refcount=0 reference=1 +ERROR cluster 3 refcount=0 reference=1 +ERROR cluster 4 refcount=0 reference=1 +ERROR cluster 5 refcount=0 reference=1 +Rebuilding refcount structure +Repairing cluster 1 refcount=1 reference=0 +The following inconsistencies were found and repaired: + + 0 leaked clusters + 5 corruptions + +Double checking the fixed image now... +No errors were found on the image. + +=== Testing empty refcount block === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed +write failed: Input/output error +ERROR cluster 0 refcount=0 reference=1 +ERROR cluster 1 refcount=0 reference=1 +ERROR cluster 2 refcount=0 reference=1 +ERROR cluster 3 refcount=0 reference=1 +Rebuilding refcount structure +Repairing cluster 1 refcount=1 reference=0 +Repairing cluster 2 refcount=1 reference=0 +The following inconsistencies were found and repaired: + + 0 leaked clusters + 4 corruptions + +Double checking the fixed image now... +No errors were found on the image. + +=== Testing empty refcount block with compressed write === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qcow2: Marking image as corrupt: Preventing invalid allocation of compressed cluster at offset 0; further corruption events will be suppressed +write failed: Input/output error +ERROR cluster 0 refcount=0 reference=1 +ERROR cluster 1 refcount=0 reference=1 +ERROR cluster 2 refcount=0 reference=1 +ERROR cluster 3 refcount=0 reference=1 +Rebuilding refcount structure +Repairing cluster 1 refcount=1 reference=0 +Repairing cluster 2 refcount=1 reference=0 +The following inconsistencies were found and repaired: + + 0 leaked clusters + 4 corruptions + +Double checking the fixed image now... +No errors were found on the image. + +=== Testing zero refcount table size === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +can't open device TEST_DIR/t.IMGFMT: Image does not contain a reference count table +ERROR cluster 0 refcount=0 reference=1 +ERROR cluster 3 refcount=0 reference=1 +Rebuilding refcount structure +The following inconsistencies were found and repaired: + + 0 leaked clusters + 2 corruptions + +Double checking the fixed image now... +No errors were found on the image. + +=== Testing incorrect refcount table offset === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed +write failed: Input/output error *** done diff --git a/tests/qemu-iotests/077 b/tests/qemu-iotests/077 index d2d2a2d6876a769617ee9ededd6e3aec3caeb0ed..b3c6fb13704ae24b504e91ab3e41a4eec512b1fe 100755 --- a/tests/qemu-iotests/077 +++ b/tests/qemu-iotests/077 @@ -188,7 +188,8 @@ EOF test_io | $QEMU_IO | _filter_qemu_io | \ sed -e 's,[0-9/]* bytes at offset [0-9]*,XXX/XXX bytes at offset XXX,g' \ -e 's/^[0-9]* \(bytes\|KiB\)/XXX bytes/' \ - -e '/Suspended/d' + -e '/Suspended/d' \ + -e '/blkdebug: Resuming request/d' echo echo "== Verify image content ==" diff --git a/tests/qemu-iotests/077.out b/tests/qemu-iotests/077.out index 16f951fd3df372cbb8717f92a3b7fb63c5d21aab..4aae82f2e2077d08d9ec4ade4d229fb4b6ffb95a 100644 --- a/tests/qemu-iotests/077.out +++ b/tests/qemu-iotests/077.out @@ -4,17 +4,14 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 == Some concurrent requests involving RMW == wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX @@ -31,51 +28,38 @@ wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'B' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'B' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'B' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'B' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' -blkdebug: Resuming request 'C' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'B' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -blkdebug: Resuming request 'A' wrote XXX/XXX bytes at offset XXX XXX bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote XXX/XXX bytes at offset XXX diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083 index 0306f112da3e45cd25832030d6de37f2632087dd..3c1adbf0fb782e8786a24bd9fa1f99277e775f22 100755 --- a/tests/qemu-iotests/083 +++ b/tests/qemu-iotests/083 @@ -86,6 +86,7 @@ EOF rm -f "$TEST_DIR/nbd.sock" + echo > "$TEST_DIR/nbd-fault-injector.out" $PYTHON nbd-fault-injector.py $extra_args "$nbd_addr" "$TEST_DIR/nbd-fault-injector.conf" >"$TEST_DIR/nbd-fault-injector.out" 2>&1 & # Wait for server to be ready @@ -94,7 +95,8 @@ EOF done # Extract the final address (port number has now been assigned in tcp case) - nbd_addr=$(sed 's/Listening on \(.*\)$/\1/' "$TEST_DIR/nbd-fault-injector.out") + nbd_addr=$(sed -n 's/^Listening on //p' \ + "$TEST_DIR/nbd-fault-injector.out") if [ "$proto" = "tcp" ]; then nbd_url="nbd+tcp://$nbd_addr/$export_name" diff --git a/tests/qemu-iotests/136 b/tests/qemu-iotests/136 index 4b994897af94d92caeecc2570757b54330c1ee47..88b97ea7c67d2f875c0c3dd744c76a0fcccfe83f 100644 --- a/tests/qemu-iotests/136 +++ b/tests/qemu-iotests/136 @@ -238,6 +238,18 @@ sector = "%d" for i in range(failed_wr_ops): ops.append("aio_write %d 512" % bad_offset) + # We need an extra aio_flush to settle all outstanding AIO + # operations before we can advance the virtual clock, so that + # the last access happens before clock_step and idle_time_ns + # will be greater than 0 + extra_flush = 0 + if rd_ops + wr_ops + invalid_rd_ops + invalid_wr_ops + \ + failed_rd_ops + failed_wr_ops > 0: + extra_flush = 1 + + if extra_flush > 0: + ops.append("aio_flush") + if failed_wr_ops > 0: highest_offset = max(highest_offset, bad_offset + 512) @@ -251,7 +263,7 @@ sector = "%d" self.total_wr_bytes += wr_ops * wr_size self.total_wr_ops += wr_ops self.total_wr_merged += wr_merged - self.total_flush_ops += flush_ops + self.total_flush_ops += flush_ops + extra_flush self.invalid_rd_ops += invalid_rd_ops self.invalid_wr_ops += invalid_wr_ops self.failed_rd_ops += failed_rd_ops diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 index 8d973b440f20d436e2933f5e226a9c06b364dd64..1d4214aca31e842d0881a2c697feaa7059d4292d 100755 --- a/tests/qemu-iotests/194 +++ b/tests/qemu-iotests/194 @@ -21,7 +21,7 @@ import iotests -iotests.verify_image_format(unsupported_fmts=['luks']) +iotests.verify_image_format(supported_fmts=['qcow2', 'qed', 'raw', 'dmg']) iotests.verify_platform(['linux']) with iotests.FilePath('source.img') as source_img_path, \ diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 0e8a33c6968ff35ef1d6813fad95d0ba849748c9..dbae7d74ba082800e9b586dbba89abd70054eefa 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -242,7 +242,7 @@ _make_test_img() if [ $IMGPROTO = "nbd" ]; then # Pass a sufficiently high number to -e that should be enough for all # tests - eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT -e 42 $TEST_IMG_FILE >/dev/null &" + eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT -e 42 -x '' $TEST_IMG_FILE >/dev/null &" sleep 1 # FIXME: qemu-nbd needs to be listening before we continue fi