[PATCH v6 23/25] iotests: cover a broken Format Extension and a combined repair
"Denis V. Lunev" <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu,gmane.comp.emulators.qemu.block |
|---|---|
| Message-ID | <[email protected]> |
From: Denis V. Lunev <[email protected]> An image which was not closed correctly may have had its Format Extension cluster reused by a guest write, which is what the reuse of those clusters is for. It has to open anyway, as the payload is intact, and it has to stop pointing at what is no longer an extension. The same damage in an image which was closed correctly is what an older qemu leaves behind, as it ignores the extension in read-write mode and truncates the file to the end of the payload on close. Both shapes of it are covered: the cluster overwritten with something which is not an extension, and the cluster truncated away with the header still pointing past the end of the file. Neither keeps the image shut, and qemu-img info is enough to tell, as it opens the image on its own. Rebuilding the used bitmap after a leak is repaired reports the errors which come with a BAT pointing a cluster twice, and those are the ones qemu-img check is there to fix, so a duplicate entry next to a leak is covered too. Cc: Stefan Hajnoczi <[email protected]> Signed-off-by: Denis V. Lunev <[email protected]> --- tests/qemu-iotests/tests/parallels-checks | 80 +++++++++++++++++++ tests/qemu-iotests/tests/parallels-checks.out | 57 +++++++++++++ 2 files changed, 137 insertions(+) diff --git a/tests/qemu-iotests/tests/parallels-checks b/tests/qemu-iotests/tests/parallels-checks index 4c8fc17fa9..084eded89d 100755 --- a/tests/qemu-iotests/tests/parallels-checks +++ b/tests/qemu-iotests/tests/parallels-checks @@ -444,6 +444,86 @@ echo "== guest data was never in doubt ==" # Clear image _make_test_img $SIZE +echo "== TEST BROKEN EXTENSION OF AN IMAGE WHICH WAS NOT CLOSED ==" + +EXT_OFF_OFFSET=56 + +echo "== add a persistent dirty bitmap ==" +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" $BITMAP 2>&1 | _filter_testdir + +ext_off=$(peek_file_le "$TEST_IMG" $EXT_OFF_OFFSET 8) + +echo "== a guest write may reuse the extension cluster, so clobber it ==" +poke_file "$TEST_IMG" $((ext_off * 512)) "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + +echo "== pretend the image was not closed correctly ==" +poke_file "$TEST_IMG" "$INUSE_OFFSET" "\x59\x6e\x6f\x74" + +echo "== the image opens, the extension is dropped ==" +{ $QEMU_IO -c "write -P 0x11 0 64k" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | + _filter_testdir | _filter_generated_node_ids + +echo "== and it stopped pointing at the broken extension ==" +echo "ext_off: $(peek_file_le "$TEST_IMG" $EXT_OFF_OFFSET 8)" + +echo "== an older qemu leaves the same damage behind a clean close ==" +_make_test_img $SIZE +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" $BITMAP 2>&1 | _filter_testdir +ext_off=$(peek_file_le "$TEST_IMG" $EXT_OFF_OFFSET 8) +poke_file "$TEST_IMG" $((ext_off * 512)) "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" +_img_info | _filter_generated_node_ids + +echo "== truncating the extension away is dropped as well ==" +_make_test_img $SIZE +$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG" $BITMAP 2>&1 | _filter_testdir +ext_off=$(peek_file_le "$TEST_IMG" $EXT_OFF_OFFSET 8) +truncate -s $((ext_off * 512)) "$TEST_IMG" +_img_info | _filter_generated_node_ids + +# Clear image +_make_test_img $SIZE + +echo "== TEST REPAIR OF A DUPLICATE ENTRY NEXT TO A LEAK ==" + +echo "== write two clusters ==" +{ $QEMU_IO -c "write -P 0x11 0 $CLUSTER_SIZE" \ + -c "write -P 0x22 $CLUSTER_SIZE $CLUSTER_SIZE" \ + "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo "== point the second BAT entry at the first cluster ==" +first=$(peek_file_le "$TEST_IMG" $BAT_OFFSET 4) +poke_file_le "$TEST_IMG" $(($BAT_OFFSET + 4)) 4 $first + +echo "== leak a cluster at the end of the image ==" +file_size=`stat --printf="%s" "$TEST_IMG"` +fallocate -xl $((file_size + CLUSTER_SIZE)) "$TEST_IMG" + +echo "== both are repaired in one go ==" +_check_test_img -r all + +echo "== and the image opens read-write afterwards ==" +{ $QEMU_IO -c "read -P 0x11 0 $CLUSTER_SIZE" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir + +# Clear image +_make_test_img $SIZE + +echo "== TEST A LEAK WHICH DOES NOT FIT AN INT ==" + +echo "== write one cluster ==" +{ $QEMU_IO -c "write -P 0x11 0 $CLUSTER_SIZE" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir + +echo "== leave 3 GiB of unused space behind it ==" +truncate -s $((3 * 1024 * 1024 * 1024)) "$TEST_IMG" + +echo "== closing the image truncates it without complaining ==" +{ $QEMU_IO -c "read -P 0x11 0 $CLUSTER_SIZE" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir + +file_size=`stat --printf="%s" "$TEST_IMG"` +echo "file size: $file_size" + +# Clear image +_make_test_img $SIZE + echo "== TEST A DUPLICATE IN THE LAST ALLOCATED BAT ENTRY ==" echo "== write two clusters ==" diff --git a/tests/qemu-iotests/tests/parallels-checks.out b/tests/qemu-iotests/tests/parallels-checks.out index 7aaa4636d7..5dc2963a98 100644 --- a/tests/qemu-iotests/tests/parallels-checks.out +++ b/tests/qemu-iotests/tests/parallels-checks.out @@ -294,6 +294,63 @@ qemu-img: warning: Dropping inconsistent bitmap b2c9e1a4-5d3f-4e8b-9a7c-6f0d1e2b read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 +== TEST BROKEN EXTENSION OF AN IMAGE WHICH WAS NOT CLOSED == +== add a persistent dirty bitmap == +== a guest write may reuse the extension cluster, so clobber it == +== pretend the image was not closed correctly == +== the image opens, the extension is dropped == +qemu-io: warning: Dropping the Format Extension of node 'NODE_NAME', which does not look like one: Wrong parallels Format Extension magic: 0xaaaaaaaaaaaaaaaa, expected: 0xab234cef23dcea87 +Repairing image was not closed correctly +Repairing space leaked at the end of the image 1048576 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== and it stopped pointing at the broken extension == +ext_off: 0 +== an older qemu leaves the same damage behind a clean close == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 +qemu-img: warning: Dropping the Format Extension of node 'NODE_NAME', which does not look like one: Wrong IMGFMT Format Extension magic: 0xaaaaaaaaaaaaaaaa, expected: 0xab234cef23dcea87 +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 4 MiB (4194304 bytes) +== truncating the extension away is dropped as well == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 +qemu-img: warning: Dropping the Format Extension of node 'NODE_NAME', which does not look like one: Format Extension is outside the image file +image: TEST_DIR/t.IMGFMT +file format: IMGFMT +virtual size: 4 MiB (4194304 bytes) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 +== TEST REPAIR OF A DUPLICATE ENTRY NEXT TO A LEAK == +== write two clusters == +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1048576/1048576 bytes at offset 1048576 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== point the second BAT entry at the first cluster == +== leak a cluster at the end of the image == +== both are repaired in one go == +Repairing space leaked at the end of the image 2097152 +Repairing duplicate offset in BAT entry 1 +The following inconsistencies were found and repaired: + + 2 leaked clusters + 1 corruptions + +Double checking the fixed image now... +No errors were found on the image. +== and the image opens read-write afterwards == +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 +== TEST A LEAK WHICH DOES NOT FIT AN INT == +== write one cluster == +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== leave 3 GiB of unused space behind it == +== closing the image truncates it without complaining == +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +file size: 2097152 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 == TEST A DUPLICATE IN THE LAST ALLOCATED BAT ENTRY == == write two clusters == wrote 1048576/1048576 bytes at offset 0 -- 2.53.0