From 1bbbf32d5fffe334531c315d7bd865fdfb67b6c5 Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Tue, 27 Aug 2019 21:59:12 +0300 Subject: [PATCH 01/16] block: Use QEMU_IS_ALIGNED Replace instances of: (n & (BDRV_SECTOR_SIZE - 1)) == 0 And: (n & ~BDRV_SECTOR_MASK) == 0 With: QEMU_IS_ALIGNED(n, BDRV_SECTOR_SIZE) Which reveals the intent of the code better, and makes it easier to locate the code checking alignment. Signed-off-by: Nir Soffer Message-id: 20190827185913.27427-2-nsoffer@redhat.com Reviewed-by: John Snow Signed-off-by: Max Reitz --- block/bochs.c | 4 ++-- block/cloop.c | 4 ++-- block/dmg.c | 4 ++-- block/io.c | 8 ++++---- block/qcow2-cluster.c | 4 ++-- block/qcow2.c | 4 ++-- block/vvfat.c | 8 ++++---- qemu-img.c | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/block/bochs.c b/block/bochs.c index 962f18592d..32bb83b268 100644 --- a/block/bochs.c +++ b/block/bochs.c @@ -248,8 +248,8 @@ bochs_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector local_qiov; int ret; - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); qemu_iovec_init(&local_qiov, qiov->niov); qemu_co_mutex_lock(&s->lock); diff --git a/block/cloop.c b/block/cloop.c index 384c9735bb..4de94876d4 100644 --- a/block/cloop.c +++ b/block/cloop.c @@ -253,8 +253,8 @@ cloop_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, int nb_sectors = bytes >> BDRV_SECTOR_BITS; int ret, i; - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); qemu_co_mutex_lock(&s->lock); diff --git a/block/dmg.c b/block/dmg.c index 45f6b28f17..4a045f2b3e 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -697,8 +697,8 @@ dmg_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, int nb_sectors = bytes >> BDRV_SECTOR_BITS; int ret, i; - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); qemu_co_mutex_lock(&s->lock); diff --git a/block/io.c b/block/io.c index 16a598fd08..f8c3596131 100644 --- a/block/io.c +++ b/block/io.c @@ -1097,8 +1097,8 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, sector_num = offset >> BDRV_SECTOR_BITS; nb_sectors = bytes >> BDRV_SECTOR_BITS; - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); assert(bytes <= BDRV_REQUEST_MAX_BYTES); assert(drv->bdrv_co_readv); @@ -1171,8 +1171,8 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, sector_num = offset >> BDRV_SECTOR_BITS; nb_sectors = bytes >> BDRV_SECTOR_BITS; - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); assert(bytes <= BDRV_REQUEST_MAX_BYTES); assert(drv->bdrv_co_writev); diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index dcacd3c450..cb44b6c6ba 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -471,8 +471,8 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, { if (bytes && bs->encrypted) { BDRVQcow2State *s = bs->opaque; - assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0); - assert((bytes & ~BDRV_SECTOR_MASK) == 0); + assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); assert(s->crypto); if (qcow2_co_encrypt(bs, cluster_offset, src_cluster_offset + offset_in_cluster, diff --git a/block/qcow2.c b/block/qcow2.c index 57734f20cf..cac18f0ba2 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2067,8 +2067,8 @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs, goto fail; } - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(cur_bytes, BDRV_SECTOR_SIZE)); if (qcow2_co_decrypt(bs, cluster_offset, offset, cluster_data, cur_bytes) < 0) { ret = -EIO; diff --git a/block/vvfat.c b/block/vvfat.c index f6c28805dd..019b8f1341 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1547,8 +1547,8 @@ vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, int nb_sectors = bytes >> BDRV_SECTOR_BITS; void *buf; - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); buf = g_try_malloc(bytes); if (bytes && buf == NULL) { @@ -3082,8 +3082,8 @@ vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, int nb_sectors = bytes >> BDRV_SECTOR_BITS; void *buf; - assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0); - assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0); + assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); buf = g_try_malloc(bytes); if (bytes && buf == NULL) { diff --git a/qemu-img.c b/qemu-img.c index 4ee436fc94..384c6f38bc 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2141,7 +2141,7 @@ static int img_convert(int argc, char **argv) int64_t sval; sval = cvtnum(optarg); - if (sval < 0 || sval & (BDRV_SECTOR_SIZE - 1) || + if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) || sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) { error_report("Invalid buffer size for sparse output specified. " "Valid sizes are multiples of %llu up to %llu. Select " From 8972571509f15bd8e31fa9ded795a11e22c0d1d3 Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Tue, 27 Aug 2019 21:59:13 +0300 Subject: [PATCH 02/16] block: Remove unused masks Replace confusing usage: ~BDRV_SECTOR_MASK With more clear: (BDRV_SECTOR_SIZE - 1) Remove BDRV_SECTOR_MASK and the unused BDRV_BLOCK_OFFSET_MASK which was it's last user. Signed-off-by: Nir Soffer Message-id: 20190827185913.27427-3-nsoffer@redhat.com Reviewed-by: Juan Quintela Reviewed-by: John Snow Signed-off-by: Max Reitz --- include/block/block.h | 2 -- migration/block.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/block/block.h b/include/block/block.h index 124ad40809..37c9de7446 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -143,7 +143,6 @@ typedef struct HDGeometry { #define BDRV_SECTOR_BITS 9 #define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS) -#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1) #define BDRV_REQUEST_MAX_SECTORS MIN(SIZE_MAX >> BDRV_SECTOR_BITS, \ INT_MAX >> BDRV_SECTOR_BITS) @@ -195,7 +194,6 @@ typedef struct HDGeometry { #define BDRV_BLOCK_ALLOCATED 0x10 #define BDRV_BLOCK_EOF 0x20 #define BDRV_BLOCK_RECURSE 0x40 -#define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue; diff --git a/migration/block.c b/migration/block.c index 0de9d84198..8e49382070 100644 --- a/migration/block.c +++ b/migration/block.c @@ -906,7 +906,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) do { addr = qemu_get_be64(f); - flags = addr & ~BDRV_SECTOR_MASK; + flags = addr & (BDRV_SECTOR_SIZE - 1); addr >>= BDRV_SECTOR_BITS; if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) { From 4ee5f4be4f174d23f59a4a1f3fd50f5673f325c5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 6 Sep 2019 13:39:20 +0200 Subject: [PATCH 03/16] tests/qemu-iotests/check: Replace "tests" with "iotests" in final status text When running "make check -j8" or something similar, the iotests are running in parallel with the other tests. So when they are printing out "Passed all xx tests" or a similar status message at the end, it might not be quite clear that this message belongs to the iotests, since the output might be mixed with the other tests. Thus change the word "tests" here to "iotests" instead to avoid confusion. Signed-off-by: Thomas Huth Message-id: 20190906113920.11271-1-thuth@redhat.com Reviewed-by: John Snow Signed-off-by: Max Reitz --- tests/qemu-iotests/check | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index a58232eefb..875399d79f 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -694,12 +694,12 @@ END { if (NR > 0) { if [ ! -z "$n_bad" -a $n_bad != 0 ] then echo "Failures:$bad" - echo "Failed $n_bad of $try tests" + echo "Failed $n_bad of $try iotests" echo "Failures:$bad" | fmt >>check.log - echo "Failed $n_bad of $try tests" >>check.log + echo "Failed $n_bad of $try iotests" >>check.log else - echo "Passed all $try tests" - echo "Passed all $try tests" >>check.log + echo "Passed all $try iotests" + echo "Passed all $try iotests" >>check.log fi needwrap=false fi From 3fb643c374233fb16c01d4c27999da505190f7cd Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 6 Sep 2019 13:35:34 +0200 Subject: [PATCH 04/16] tests/Makefile: Do not print the name of the check-block.sh shell script The check script is already printing out which iotest is currently running, so printing out the name of the check-block.sh shell script looks superfluous here. Signed-off-by: Thomas Huth Message-id: 20190906113534.10907-1-thuth@redhat.com Acked-by: John Snow Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- tests/Makefile.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index b39860a8d0..793632ca72 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -1100,7 +1100,7 @@ QEMU_IOTESTS_HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = tests/qemu check-tests/check-block.sh: tests/check-block.sh qemu-img$(EXESUF) \ qemu-io$(EXESUF) qemu-nbd$(EXESUF) $(QEMU_IOTESTS_HELPERS-y) \ $(patsubst %,%/all,$(filter %-softmmu,$(TARGET_DIRS))) - $< + @$< .PHONY: $(patsubst %, check-%, $(check-qapi-schema-y)) $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json From 9407cf862ceabddb22ae4bad5a0c8cb5ef6979c5 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 16 Aug 2019 18:30:11 +0300 Subject: [PATCH 05/16] tests/qemu-iotests: Fix qemu-io related output in 026.out.nocache qemu-io now prefixes its error and warnings with "qemu-io:". 36b9986b08787019e fixed a lot of iotests output but forget about 026.out.nocache. Fix it too. Fixes: 99e98d7c9fc1a1639fad ("qemu-io: Use error_[gs]et_progname()") Signed-off-by: Vladimir Sementsov-Ogievskiy Message-id: 20190816153015.447957-2-vsementsov@virtuozzo.com Reviewed-by: John Snow Signed-off-by: Max Reitz --- tests/qemu-iotests/026.out.nocache | 168 ++++++++++++++--------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache index 1ca6cda15c..6dda95dfb4 100644 --- a/tests/qemu-iotests/026.out.nocache +++ b/tests/qemu-iotests/026.out.nocache @@ -14,8 +14,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -23,8 +23,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -42,8 +42,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -51,8 +51,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -136,8 +136,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -146,8 +146,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -168,8 +168,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -178,8 +178,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_update; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -198,15 +198,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error 1 leaked clusters were found on the image. @@ -224,15 +224,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc_write; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 1 leaked clusters were found on the image. @@ -250,15 +250,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -274,15 +274,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: write_aio; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -298,15 +298,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -322,15 +322,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_load; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -346,15 +346,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -370,15 +370,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_update_part; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -394,15 +394,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 5; imm: off; once: off; write -b -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -418,15 +418,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -485,8 +485,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 55 leaked clusters were found on the image. @@ -494,8 +494,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 251 leaked clusters were found on the image. @@ -513,15 +513,15 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -537,8 +537,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 10 leaked clusters were found on the image. @@ -546,8 +546,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -565,8 +565,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 10 leaked clusters were found on the image. @@ -574,8 +574,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -593,8 +593,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 10 leaked clusters were found on the image. @@ -602,8 +602,8 @@ This means waste of disk space, but no harm to data. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -b -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 23 leaked clusters were found on the image. @@ -639,8 +639,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 5; imm: off; once: off -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -651,8 +651,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_write_table; errno: 28; imm: off; once: off -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 @@ -663,8 +663,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_activate_table; errno: 5; imm: off; once: off -Failed to flush the L2 table cache: Input/output error -Failed to flush the refcount block cache: Input/output error +qemu-io: Failed to flush the L2 table cache: Input/output error +qemu-io: Failed to flush the refcount block cache: Input/output error write failed: Input/output error 96 leaked clusters were found on the image. @@ -677,8 +677,8 @@ No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_grow_activate_table; errno: 28; imm: off; once: off -Failed to flush the L2 table cache: No space left on device -Failed to flush the refcount block cache: No space left on device +qemu-io: Failed to flush the L2 table cache: No space left on device +qemu-io: Failed to flush the refcount block cache: No space left on device write failed: No space left on device 96 leaked clusters were found on the image. From 0487861685294660b23bc146e1ebd5304aa8bbe0 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 10 Sep 2019 14:41:30 +0200 Subject: [PATCH 06/16] curl: Keep pointer to the CURLState in CURLSocket A follow-up patch will make curl_multi_do() and curl_multi_read() take a CURLSocket instead of the CURLState. They still need the latter, though, so add a pointer to it to the former. Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz Reviewed-by: John Snow Message-id: 20190910124136.10565-2-mreitz@redhat.com Reviewed-by: Maxim Levitsky Signed-off-by: Max Reitz --- block/curl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/curl.c b/block/curl.c index d4c8e94f3e..92dc2f630e 100644 --- a/block/curl.c +++ b/block/curl.c @@ -80,6 +80,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, #define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5 struct BDRVCURLState; +struct CURLState; static bool libcurl_initialized; @@ -97,6 +98,7 @@ typedef struct CURLAIOCB { typedef struct CURLSocket { int fd; + struct CURLState *state; QLIST_ENTRY(CURLSocket) next; } CURLSocket; @@ -180,6 +182,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, if (!socket) { socket = g_new0(CURLSocket, 1); socket->fd = fd; + socket->state = state; QLIST_INSERT_HEAD(&state->sockets, socket, next); } socket = NULL; From 007f339b1099af46a008dac438ca0943e31dba72 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 10 Sep 2019 14:41:31 +0200 Subject: [PATCH 07/16] curl: Keep *socket until the end of curl_sock_cb() This does not really change anything, but it makes the code a bit easier to follow once we use @socket as the opaque pointer for aio_set_fd_handler(). Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz Message-id: 20190910124136.10565-3-mreitz@redhat.com Reviewed-by: Maxim Levitsky Reviewed-by: John Snow Signed-off-by: Max Reitz --- block/curl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block/curl.c b/block/curl.c index 92dc2f630e..95d7b77dc0 100644 --- a/block/curl.c +++ b/block/curl.c @@ -172,10 +172,6 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, QLIST_FOREACH(socket, &state->sockets, next) { if (socket->fd == fd) { - if (action == CURL_POLL_REMOVE) { - QLIST_REMOVE(socket, next); - g_free(socket); - } break; } } @@ -185,7 +181,6 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, socket->state = state; QLIST_INSERT_HEAD(&state->sockets, socket, next); } - socket = NULL; trace_curl_sock_cb(action, (int)fd); switch (action) { @@ -207,6 +202,11 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, break; } + if (action == CURL_POLL_REMOVE) { + QLIST_REMOVE(socket, next); + g_free(socket); + } + return 0; } From 948403bcb1c7e71dcbe8ab8479cf3934a0efcbb5 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 10 Sep 2019 14:41:32 +0200 Subject: [PATCH 08/16] curl: Check completion in curl_multi_do() While it is more likely that transfers complete after some file descriptor has data ready to read, we probably should not rely on it. Better be safe than sorry and call curl_multi_check_completion() in curl_multi_do(), too, just like it is done in curl_multi_read(). With this change, curl_multi_do() and curl_multi_read() are actually the same, so drop curl_multi_read() and use curl_multi_do() as the sole FD handler. Signed-off-by: Max Reitz Message-id: 20190910124136.10565-4-mreitz@redhat.com Reviewed-by: Maxim Levitsky Reviewed-by: John Snow Signed-off-by: Max Reitz --- block/curl.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/block/curl.c b/block/curl.c index 95d7b77dc0..5838afef99 100644 --- a/block/curl.c +++ b/block/curl.c @@ -139,7 +139,6 @@ typedef struct BDRVCURLState { static void curl_clean_state(CURLState *s); static void curl_multi_do(void *arg); -static void curl_multi_read(void *arg); #ifdef NEED_CURL_TIMER_CALLBACK /* Called from curl_multi_do_locked, with s->mutex held. */ @@ -186,7 +185,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, switch (action) { case CURL_POLL_IN: aio_set_fd_handler(s->aio_context, fd, false, - curl_multi_read, NULL, NULL, state); + curl_multi_do, NULL, NULL, state); break; case CURL_POLL_OUT: aio_set_fd_handler(s->aio_context, fd, false, @@ -194,7 +193,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, break; case CURL_POLL_INOUT: aio_set_fd_handler(s->aio_context, fd, false, - curl_multi_read, curl_multi_do, NULL, state); + curl_multi_do, curl_multi_do, NULL, state); break; case CURL_POLL_REMOVE: aio_set_fd_handler(s->aio_context, fd, false, @@ -416,15 +415,6 @@ static void curl_multi_do(void *arg) { CURLState *s = (CURLState *)arg; - qemu_mutex_lock(&s->s->mutex); - curl_multi_do_locked(s); - qemu_mutex_unlock(&s->s->mutex); -} - -static void curl_multi_read(void *arg) -{ - CURLState *s = (CURLState *)arg; - qemu_mutex_lock(&s->s->mutex); curl_multi_do_locked(s); curl_multi_check_completion(s->s); From 9dbad87d25587ff640ef878f7b6159fc368ff541 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 10 Sep 2019 14:41:33 +0200 Subject: [PATCH 09/16] curl: Pass CURLSocket to curl_multi_do() curl_multi_do_locked() currently marks all sockets as ready. That is not only inefficient, but in fact unsafe (the loop is). A follow-up patch will change that, but to do so, curl_multi_do_locked() needs to know exactly which socket is ready; and that is accomplished by this patch here. Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz Message-id: 20190910124136.10565-5-mreitz@redhat.com Reviewed-by: Maxim Levitsky Reviewed-by: John Snow Signed-off-by: Max Reitz --- block/curl.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/block/curl.c b/block/curl.c index 5838afef99..cf2686218d 100644 --- a/block/curl.c +++ b/block/curl.c @@ -185,15 +185,15 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, switch (action) { case CURL_POLL_IN: aio_set_fd_handler(s->aio_context, fd, false, - curl_multi_do, NULL, NULL, state); + curl_multi_do, NULL, NULL, socket); break; case CURL_POLL_OUT: aio_set_fd_handler(s->aio_context, fd, false, - NULL, curl_multi_do, NULL, state); + NULL, curl_multi_do, NULL, socket); break; case CURL_POLL_INOUT: aio_set_fd_handler(s->aio_context, fd, false, - curl_multi_do, curl_multi_do, NULL, state); + curl_multi_do, curl_multi_do, NULL, socket); break; case CURL_POLL_REMOVE: aio_set_fd_handler(s->aio_context, fd, false, @@ -392,9 +392,10 @@ static void curl_multi_check_completion(BDRVCURLState *s) } /* Called with s->mutex held. */ -static void curl_multi_do_locked(CURLState *s) +static void curl_multi_do_locked(CURLSocket *ready_socket) { CURLSocket *socket, *next_socket; + CURLState *s = ready_socket->state; int running; int r; @@ -413,12 +414,13 @@ static void curl_multi_do_locked(CURLState *s) static void curl_multi_do(void *arg) { - CURLState *s = (CURLState *)arg; + CURLSocket *socket = arg; + BDRVCURLState *s = socket->state->s; - qemu_mutex_lock(&s->s->mutex); - curl_multi_do_locked(s); - curl_multi_check_completion(s->s); - qemu_mutex_unlock(&s->s->mutex); + qemu_mutex_lock(&s->mutex); + curl_multi_do_locked(socket); + curl_multi_check_completion(s); + qemu_mutex_unlock(&s->mutex); } static void curl_multi_timeout_do(void *arg) From 9abaf9fc474c3dd53e8e119326abc774c977c331 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 10 Sep 2019 14:41:34 +0200 Subject: [PATCH 10/16] curl: Report only ready sockets Instead of reporting all sockets to cURL, only report the one that has caused curl_multi_do_locked() to be called. This lets us get rid of the QLIST_FOREACH_SAFE() list, which was actually wrong: SAFE foreaches are only safe when the current element is removed in each iteration. If it possible for the list to be concurrently modified, we cannot guarantee that only the current element will be removed. Therefore, we must not use QLIST_FOREACH_SAFE() here. Fixes: ff5ca1664af85b24a4180d595ea6873fd3deac57 Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz Message-id: 20190910124136.10565-6-mreitz@redhat.com Reviewed-by: Maxim Levitsky Reviewed-by: John Snow Signed-off-by: Max Reitz --- block/curl.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/block/curl.c b/block/curl.c index cf2686218d..fd70f1ebc4 100644 --- a/block/curl.c +++ b/block/curl.c @@ -392,24 +392,19 @@ static void curl_multi_check_completion(BDRVCURLState *s) } /* Called with s->mutex held. */ -static void curl_multi_do_locked(CURLSocket *ready_socket) +static void curl_multi_do_locked(CURLSocket *socket) { - CURLSocket *socket, *next_socket; - CURLState *s = ready_socket->state; + BDRVCURLState *s = socket->state->s; int running; int r; - if (!s->s->multi) { + if (!s->multi) { return; } - /* Need to use _SAFE because curl_multi_socket_action() may trigger - * curl_sock_cb() which might modify this list */ - QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) { - do { - r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running); - } while (r == CURLM_CALL_MULTI_PERFORM); - } + do { + r = curl_multi_socket_action(s->multi, socket->fd, 0, &running); + } while (r == CURLM_CALL_MULTI_PERFORM); } static void curl_multi_do(void *arg) From bfb23b480a49114315877aacf700b49453e0f9d9 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 10 Sep 2019 14:41:35 +0200 Subject: [PATCH 11/16] curl: Handle success in multi_check_completion Background: As of cURL 7.59.0, it verifies that several functions are not called from within a callback. Among these functions is curl_multi_add_handle(). curl_read_cb() is a callback from cURL and not a coroutine. Waking up acb->co will lead to entering it then and there, which means the current request will settle and the caller (if it runs in the same coroutine) may then issue the next request. In such a case, we will enter curl_setup_preadv() effectively from within curl_read_cb(). Calling curl_multi_add_handle() will then fail and the new request will not be processed. Fix this by not letting curl_read_cb() wake up acb->co. Instead, leave the whole business of settling the AIOCB objects to curl_multi_check_completion() (which is called from our timer callback and our FD handler, so not from any cURL callbacks). Reported-by: Natalie Gavrielov Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1740193 Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz Message-id: 20190910124136.10565-7-mreitz@redhat.com Reviewed-by: John Snow Reviewed-by: Maxim Levitsky Signed-off-by: Max Reitz --- block/curl.c | 71 ++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/block/curl.c b/block/curl.c index fd70f1ebc4..c343c7ed3d 100644 --- a/block/curl.c +++ b/block/curl.c @@ -229,7 +229,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) { CURLState *s = ((CURLState*)opaque); size_t realsize = size * nmemb; - int i; trace_curl_read_cb(realsize); @@ -245,32 +244,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) memcpy(s->orig_buf + s->buf_off, ptr, realsize); s->buf_off += realsize; - for(i=0; iacb[i]; - - if (!acb) - continue; - - if ((s->buf_off >= acb->end)) { - size_t request_length = acb->bytes; - - qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start, - acb->end - acb->start); - - if (acb->end - acb->start < request_length) { - size_t offset = acb->end - acb->start; - qemu_iovec_memset(acb->qiov, offset, 0, - request_length - offset); - } - - acb->ret = 0; - s->acb[i] = NULL; - qemu_mutex_unlock(&s->s->mutex); - aio_co_wake(acb->co); - qemu_mutex_lock(&s->s->mutex); - } - } - read_end: /* curl will error out if we do not return this value */ return size * nmemb; @@ -351,13 +324,14 @@ static void curl_multi_check_completion(BDRVCURLState *s) break; if (msg->msg == CURLMSG_DONE) { + int i; CURLState *state = NULL; + bool error = msg->data.result != CURLE_OK; + curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char **)&state); - /* ACBs for successful messages get completed in curl_read_cb */ - if (msg->data.result != CURLE_OK) { - int i; + if (error) { static int errcount = 100; /* Don't lose the original error message from curl, since @@ -369,20 +343,35 @@ static void curl_multi_check_completion(BDRVCURLState *s) error_report("curl: further errors suppressed"); } } + } - for (i = 0; i < CURL_NUM_ACB; i++) { - CURLAIOCB *acb = state->acb[i]; + for (i = 0; i < CURL_NUM_ACB; i++) { + CURLAIOCB *acb = state->acb[i]; - if (acb == NULL) { - continue; - } - - acb->ret = -EIO; - state->acb[i] = NULL; - qemu_mutex_unlock(&s->mutex); - aio_co_wake(acb->co); - qemu_mutex_lock(&s->mutex); + if (acb == NULL) { + continue; } + + if (!error) { + /* Assert that we have read all data */ + assert(state->buf_off >= acb->end); + + qemu_iovec_from_buf(acb->qiov, 0, + state->orig_buf + acb->start, + acb->end - acb->start); + + if (acb->end - acb->start < acb->bytes) { + size_t offset = acb->end - acb->start; + qemu_iovec_memset(acb->qiov, offset, 0, + acb->bytes - offset); + } + } + + acb->ret = error ? -EIO : 0; + state->acb[i] = NULL; + qemu_mutex_unlock(&s->mutex); + aio_co_wake(acb->co); + qemu_mutex_lock(&s->mutex); } curl_clean_state(state); From c34dc07f9f01cf686e512f939aece744723072cd Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Tue, 10 Sep 2019 14:41:36 +0200 Subject: [PATCH 12/16] curl: Check curl_multi_add_handle()'s return code If we had done that all along, debugging would have been much simpler. (Also, I/O errors are better than hangs.) Signed-off-by: Max Reitz Message-id: 20190910124136.10565-8-mreitz@redhat.com Reviewed-by: Maxim Levitsky Reviewed-by: John Snow Signed-off-by: Max Reitz --- block/curl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/block/curl.c b/block/curl.c index c343c7ed3d..f86299378e 100644 --- a/block/curl.c +++ b/block/curl.c @@ -882,7 +882,13 @@ static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) trace_curl_setup_preadv(acb->bytes, start, state->range); curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); - curl_multi_add_handle(s->multi, state->curl); + if (curl_multi_add_handle(s->multi, state->curl) != CURLM_OK) { + state->acb[0] = NULL; + acb->ret = -EIO; + + curl_clean_state(state); + goto out; + } /* Tell curl it needs to kick things off */ curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); From d876bf676f5e7c6aa9ac64555e48cba8734ecb2f Mon Sep 17 00:00:00 2001 From: Sergio Lopez Date: Wed, 11 Sep 2019 12:03:16 +0200 Subject: [PATCH 13/16] blockjob: update nodes head while removing all bdrv block_job_remove_all_bdrv() iterates through job->nodes, calling bdrv_root_unref_child() for each entry. The call to the latter may reach child_job_[can_]set_aio_ctx(), which will also attempt to traverse job->nodes, potentially finding entries that where freed on previous iterations. To avoid this situation, update job->nodes head on each iteration to ensure that already freed entries are no longer linked to the list. RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631 Signed-off-by: Sergio Lopez Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz Message-id: 20190911100316.32282-1-mreitz@redhat.com Reviewed-by: Sergio Lopez Signed-off-by: Max Reitz --- blockjob.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/blockjob.c b/blockjob.c index 2abed0f551..c6e20e2fcd 100644 --- a/blockjob.c +++ b/blockjob.c @@ -175,14 +175,23 @@ static const BdrvChildRole child_job = { void block_job_remove_all_bdrv(BlockJob *job) { - GSList *l; - for (l = job->nodes; l; l = l->next) { + /* + * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(), + * which will also traverse job->nodes, so consume the list one by + * one to make sure that such a concurrent access does not attempt + * to process an already freed BdrvChild. + */ + while (job->nodes) { + GSList *l = job->nodes; BdrvChild *c = l->data; + + job->nodes = l->next; + bdrv_op_unblock_all(c->bs, job->blocker); bdrv_root_unref_child(c); + + g_slist_free_1(l); } - g_slist_free(job->nodes); - job->nodes = NULL; } bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs) From 38e7d54bdc518b5a05a922467304bcace2396945 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Sun, 15 Sep 2019 23:36:53 +0300 Subject: [PATCH 14/16] block/qcow2: Fix corruption introduced by commit 8ac0f15f335 This fixes subtle corruption introduced by luks threaded encryption in commit 8ac0f15f335 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1745922 The corruption happens when we do a write that * writes to two or more unallocated clusters at once * doesn't fully cover the first sector * doesn't fully cover the last sector * uses luks encryption In this case, when allocating the new clusters we COW both areas prior to the write and after the write, and we encrypt them. The above mentioned commit accidentally made it so we encrypt the second COW area using the physical cluster offset of the first area. The problem is that offset_in_cluster in do_perform_cow_encrypt can be larger that the cluster size, thus cluster_offset will no longer point to the start of the cluster at which encrypted area starts. Next patch in this series will refactor the code to avoid all these assumptions. In the bugreport that was triggered by rebasing a luks image to new, zero filled base, which lot of such writes, and causes some files with zero areas to contain garbage there instead. But as described above it can happen elsewhere as well Signed-off-by: Maxim Levitsky Reviewed-by: Vladimir Sementsov-Ogievskiy Message-id: 20190915203655.21638-2-mlevitsk@redhat.com Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- block/qcow2-cluster.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index cb44b6c6ba..cac0b6c7ba 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -474,9 +474,10 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); assert(s->crypto); - if (qcow2_co_encrypt(bs, cluster_offset, - src_cluster_offset + offset_in_cluster, - buffer, bytes) < 0) { + if (qcow2_co_encrypt(bs, + start_of_cluster(s, cluster_offset + offset_in_cluster), + src_cluster_offset + offset_in_cluster, + buffer, bytes) < 0) { return false; } } From 603fbd076c76438b15ec842f0e2d1ba4867dfd00 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Sun, 15 Sep 2019 23:36:54 +0300 Subject: [PATCH 15/16] block/qcow2: refactor encryption code * Change the qcow2_co_{encrypt|decrypt} to just receive full host and guest offsets and use this function directly instead of calling do_perform_cow_encrypt (which is removed by that patch). * Adjust qcow2_co_encdec to take full host and guest offsets as well. * Document the qcow2_co_{encrypt|decrypt} arguments to prevent the bug fixed in former commit from hopefully happening again. Signed-off-by: Maxim Levitsky Message-id: 20190915203655.21638-3-mlevitsk@redhat.com Reviewed-by: Vladimir Sementsov-Ogievskiy [mreitz: Let perform_cow() return the error value returned by qcow2_co_encrypt(), as proposed by Vladimir] Signed-off-by: Max Reitz --- block/qcow2-cluster.c | 41 +++++++++------------------- block/qcow2-threads.c | 63 +++++++++++++++++++++++++++++++++---------- block/qcow2.c | 5 ++-- block/qcow2.h | 8 +++--- 4 files changed, 69 insertions(+), 48 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index cac0b6c7ba..8d5fa1539c 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -462,28 +462,6 @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs, return 0; } -static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, - uint64_t src_cluster_offset, - uint64_t cluster_offset, - unsigned offset_in_cluster, - uint8_t *buffer, - unsigned bytes) -{ - if (bytes && bs->encrypted) { - BDRVQcow2State *s = bs->opaque; - assert(QEMU_IS_ALIGNED(offset_in_cluster, BDRV_SECTOR_SIZE)); - assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE)); - assert(s->crypto); - if (qcow2_co_encrypt(bs, - start_of_cluster(s, cluster_offset + offset_in_cluster), - src_cluster_offset + offset_in_cluster, - buffer, bytes) < 0) { - return false; - } - } - return true; -} - static int coroutine_fn do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset, unsigned offset_in_cluster, @@ -891,12 +869,19 @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m) /* Encrypt the data if necessary before writing it */ if (bs->encrypted) { - if (!do_perform_cow_encrypt(bs, m->offset, m->alloc_offset, - start->offset, start_buffer, - start->nb_bytes) || - !do_perform_cow_encrypt(bs, m->offset, m->alloc_offset, - end->offset, end_buffer, end->nb_bytes)) { - ret = -EIO; + ret = qcow2_co_encrypt(bs, + m->alloc_offset + start->offset, + m->offset + start->offset, + start_buffer, start->nb_bytes); + if (ret < 0) { + goto fail; + } + + ret = qcow2_co_encrypt(bs, + m->alloc_offset + end->offset, + m->offset + end->offset, + end_buffer, end->nb_bytes); + if (ret < 0) { goto fail; } } diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c index 3b1e63fe41..8f5a0d1ebe 100644 --- a/block/qcow2-threads.c +++ b/block/qcow2-threads.c @@ -234,35 +234,70 @@ static int qcow2_encdec_pool_func(void *opaque) } static int coroutine_fn -qcow2_co_encdec(BlockDriverState *bs, uint64_t file_cluster_offset, - uint64_t offset, void *buf, size_t len, Qcow2EncDecFunc func) +qcow2_co_encdec(BlockDriverState *bs, uint64_t host_offset, + uint64_t guest_offset, void *buf, size_t len, + Qcow2EncDecFunc func) { BDRVQcow2State *s = bs->opaque; Qcow2EncDecData arg = { .block = s->crypto, - .offset = s->crypt_physical_offset ? - file_cluster_offset + offset_into_cluster(s, offset) : - offset, + .offset = s->crypt_physical_offset ? host_offset : guest_offset, .buf = buf, .len = len, .func = func, }; - return qcow2_co_process(bs, qcow2_encdec_pool_func, &arg); + assert(QEMU_IS_ALIGNED(guest_offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(host_offset, BDRV_SECTOR_SIZE)); + assert(QEMU_IS_ALIGNED(len, BDRV_SECTOR_SIZE)); + assert(s->crypto); + + return len == 0 ? 0 : qcow2_co_process(bs, qcow2_encdec_pool_func, &arg); } +/* + * qcow2_co_encrypt() + * + * Encrypts one or more contiguous aligned sectors + * + * @host_offset - underlying storage offset of the first sector of the + * data to be encrypted + * + * @guest_offset - guest (virtual) offset of the first sector of the + * data to be encrypted + * + * @buf - buffer with the data to encrypt, that after encryption + * will be written to the underlying storage device at + * @host_offset + * + * @len - length of the buffer (must be a BDRV_SECTOR_SIZE multiple) + * + * Depending on the encryption method, @host_offset and/or @guest_offset + * may be used for generating the initialization vector for + * encryption. + * + * Note that while the whole range must be aligned on sectors, it + * does not have to be aligned on clusters and can also cross cluster + * boundaries + */ int coroutine_fn -qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset, - uint64_t offset, void *buf, size_t len) +qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset, + uint64_t guest_offset, void *buf, size_t len) { - return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len, - qcrypto_block_encrypt); + return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len, + qcrypto_block_encrypt); } +/* + * qcow2_co_decrypt() + * + * Decrypts one or more contiguous aligned sectors + * Similar to qcow2_co_encrypt + */ int coroutine_fn -qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset, - uint64_t offset, void *buf, size_t len) +qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset, + uint64_t guest_offset, void *buf, size_t len) { - return qcow2_co_encdec(bs, file_cluster_offset, offset, buf, len, - qcrypto_block_decrypt); + return qcow2_co_encdec(bs, host_offset, guest_offset, buf, len, + qcrypto_block_decrypt); } diff --git a/block/qcow2.c b/block/qcow2.c index cac18f0ba2..4d16393e61 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2069,7 +2069,8 @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs, assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)); assert(QEMU_IS_ALIGNED(cur_bytes, BDRV_SECTOR_SIZE)); - if (qcow2_co_decrypt(bs, cluster_offset, offset, + if (qcow2_co_decrypt(bs, cluster_offset + offset_in_cluster, + offset, cluster_data, cur_bytes) < 0) { ret = -EIO; goto fail; @@ -2288,7 +2289,7 @@ static coroutine_fn int qcow2_co_pwritev_part( qemu_iovec_to_buf(qiov, qiov_offset + bytes_done, cluster_data, cur_bytes); - if (qcow2_co_encrypt(bs, cluster_offset, offset, + if (qcow2_co_encrypt(bs, cluster_offset + offset_in_cluster, offset, cluster_data, cur_bytes) < 0) { ret = -EIO; goto out_unlocked; diff --git a/block/qcow2.h b/block/qcow2.h index 998bcdaef1..a488d761ff 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -758,10 +758,10 @@ ssize_t coroutine_fn qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size, const void *src, size_t src_size); int coroutine_fn -qcow2_co_encrypt(BlockDriverState *bs, uint64_t file_cluster_offset, - uint64_t offset, void *buf, size_t len); +qcow2_co_encrypt(BlockDriverState *bs, uint64_t host_offset, + uint64_t guest_offset, void *buf, size_t len); int coroutine_fn -qcow2_co_decrypt(BlockDriverState *bs, uint64_t file_cluster_offset, - uint64_t offset, void *buf, size_t len); +qcow2_co_decrypt(BlockDriverState *bs, uint64_t host_offset, + uint64_t guest_offset, void *buf, size_t len); #endif From 1825cc0783ccf0ec5d9f0b225a99b340bdd4c68f Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Sun, 15 Sep 2019 23:36:55 +0300 Subject: [PATCH 16/16] qemu-iotests: Add test for bz #1745922 Signed-off-by: Maxim Levitsky Tested-by: Vladimir Sementsov-Ogievskiy Message-id: 20190915203655.21638-4-mlevitsk@redhat.com Reviewed-by: Max Reitz Signed-off-by: Max Reitz --- tests/qemu-iotests/263 | 91 ++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/263.out | 40 +++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 132 insertions(+) create mode 100755 tests/qemu-iotests/263 create mode 100644 tests/qemu-iotests/263.out diff --git a/tests/qemu-iotests/263 b/tests/qemu-iotests/263 new file mode 100755 index 0000000000..d2c030fae9 --- /dev/null +++ b/tests/qemu-iotests/263 @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# +# Test encrypted write that crosses cluster boundary of two unallocated clusters +# Based on 188 +# +# Copyright (C) 2019 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 . +# + +# creator +owner=mlevitsk@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto generic +_supported_os Linux + + +size=1M + +SECRET="secret,id=sec0,data=astrochicken" +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT + + +_run_test() +{ + echo "== reading the whole image ==" + $QEMU_IO --object $SECRET -c "read -P 0 0 $size" --image-opts "$1" | _filter_qemu_io | _filter_testdir + + echo + echo "== write two 512 byte sectors on a cluster boundary ==" + $QEMU_IO --object $SECRET -c "write -P 0xAA 0xFE00 0x400" --image-opts "$1" | _filter_qemu_io | _filter_testdir + + echo + echo "== verify that the rest of the image is not changed ==" + $QEMU_IO --object $SECRET -c "read -P 0x00 0x00000 0xFE00" --image-opts "$1" | _filter_qemu_io | _filter_testdir + $QEMU_IO --object $SECRET -c "read -P 0xAA 0x0FE00 0x400" --image-opts "$1" | _filter_qemu_io | _filter_testdir + $QEMU_IO --object $SECRET -c "read -P 0x00 0x10200 0xEFE00" --image-opts "$1" | _filter_qemu_io | _filter_testdir + +} + + +echo +echo "testing LUKS qcow2 encryption" +echo + +_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,cluster_size=64K" $size +_run_test "driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG" +_cleanup_test_img + +echo +echo "testing legacy AES qcow2 encryption" +echo + + +_make_test_img --object $SECRET -o "encrypt.format=aes,encrypt.key-secret=sec0,cluster_size=64K" $size +_run_test "driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG" +_cleanup_test_img + + + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/263.out b/tests/qemu-iotests/263.out new file mode 100644 index 0000000000..0c982c55cb --- /dev/null +++ b/tests/qemu-iotests/263.out @@ -0,0 +1,40 @@ +QA output created by 263 + +testing LUKS qcow2 encryption + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10 +== reading the whole image == +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== write two 512 byte sectors on a cluster boundary == +wrote 1024/1024 bytes at offset 65024 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== verify that the rest of the image is not changed == +read 65024/65024 bytes at offset 0 +63.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 1024/1024 bytes at offset 65024 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 982528/982528 bytes at offset 66048 +959.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +testing legacy AES qcow2 encryption + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=aes encrypt.key-secret=sec0 +== reading the whole image == +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== write two 512 byte sectors on a cluster boundary == +wrote 1024/1024 bytes at offset 65024 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +== verify that the rest of the image is not changed == +read 65024/65024 bytes at offset 0 +63.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 1024/1024 bytes at offset 65024 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 982528/982528 bytes at offset 66048 +959.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 6082c74806..5d3da937e4 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -274,5 +274,6 @@ 257 rw 258 rw quick 262 rw quick migration +263 rw quick 265 rw auto quick 266 rw quick