Add a test for conversion between different refcount widths and errors specific to certain widths (i.e. snapshots with refcount_width=1).
Signed-off-by: Max Reitz <mre...@redhat.com> --- tests/qemu-iotests/112 | 252 +++++++++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/112.out | 131 +++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 384 insertions(+) create mode 100755 tests/qemu-iotests/112 create mode 100644 tests/qemu-iotests/112.out diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112 new file mode 100755 index 0000000..e824d8a --- /dev/null +++ b/tests/qemu-iotests/112 @@ -0,0 +1,252 @@ +#!/bin/bash +# +# Test cases for different refcount_widths +# +# Copyright (C) 2014 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 <http://www.gnu.org/licenses/>. +# + +# creator +owner=mre...@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +tmp=/tmp/$$ +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 + +# This tests qcow2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux +# This test will set refcount_width on its own which would conflict with the +# manual setting; compat will be overridden as well +_unsupported_imgopts refcount_width 'compat=0.10' + +function print_refcount_width() +{ + $QEMU_IMG info "$TEST_IMG" | sed -n '/refcount width:/ s/^ *//p' +} + +echo +echo '=== refcount_width limits ===' +echo + +# Must be positive (non-zero) +IMGOPTS="$IMGOPTS,refcount_width=0" _make_test_img 64M +# Must be positive (non-negative) +IMGOPTS="$IMGOPTS,refcount_width=-1" _make_test_img 64M +# May not exceed 64 +IMGOPTS="$IMGOPTS,refcount_width=128" _make_test_img 64M +# Must be a power of two +IMGOPTS="$IMGOPTS,refcount_width=42" _make_test_img 64M + +# 1 is the minimum +IMGOPTS="$IMGOPTS,refcount_width=1" _make_test_img 64M +print_refcount_width + +# 64 is the maximum +IMGOPTS="$IMGOPTS,refcount_width=64" _make_test_img 64M +print_refcount_width + +# 16 is the default +_make_test_img 64M +print_refcount_width + +echo +echo '=== refcount_width and compat=0.10 ===' +echo + +# Should work +IMGOPTS="$IMGOPTS,compat=0.10,refcount_width=16" _make_test_img 64M +print_refcount_width + +# Should not work +IMGOPTS="$IMGOPTS,compat=0.10,refcount_width=1" _make_test_img 64M +IMGOPTS="$IMGOPTS,compat=0.10,refcount_width=64" _make_test_img 64M + + +echo +echo '=== Snapshot limit on refcount_width=1 ===' +echo + +IMGOPTS="$IMGOPTS,refcount_width=1" _make_test_img 64M +print_refcount_width + +$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io + +# Should fail for now; in the future, this might be supported by automatically +# copying all clusters with overflowing refcount +$QEMU_IMG snapshot -c foo "$TEST_IMG" + +# The new L1 table could/should be leaked +_check_test_img + +echo +echo '=== Snapshot limit on refcount_width=2 ===' +echo + +IMGOPTS="$IMGOPTS,refcount_width=2" _make_test_img 64M +print_refcount_width + +$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io + +# Should succeed +$QEMU_IMG snapshot -c foo "$TEST_IMG" +$QEMU_IMG snapshot -c bar "$TEST_IMG" +# Should fail (4th reference) +$QEMU_IMG snapshot -c baz "$TEST_IMG" + +# The new L1 table could/should be leaked +_check_test_img + +echo +echo '=== Compressed clusters with refcount_width=1 ===' +echo + +IMGOPTS="$IMGOPTS,refcount_width=1" _make_test_img 64M +print_refcount_width + +# Both should fit into a single host cluster; instead of failing to increase the +# refcount of that cluster, qemu should just allocate a new cluster and make +# this operation succeed +$QEMU_IO -c 'write -P 0 -c 0 64k' \ + -c 'write -P 1 -c 64k 64k' \ + "$TEST_IMG" | _filter_qemu_io + +_check_test_img + +echo +echo '=== Amend from refcount_width=16 to refcount_width=1 ===' +echo + +_make_test_img 64M +print_refcount_width + +$QEMU_IO -c 'write 16M 32M' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG amend -o refcount_width=1 "$TEST_IMG" +_check_test_img +print_refcount_width + +echo +echo '=== Amend from refcount_width=1 to refcount_width=64 ===' +echo + +$QEMU_IMG amend -o refcount_width=64 "$TEST_IMG" +_check_test_img +print_refcount_width + +echo +echo '=== Amend to compat=0.10 ===' +echo + +# Should not work because refcount_width needs to be 16 for compat=0.10 +$QEMU_IMG amend -o compat=0.10 "$TEST_IMG" +print_refcount_width +# Should work +$QEMU_IMG amend -o compat=0.10,refcount_width=16 "$TEST_IMG" +_check_test_img +print_refcount_width + +# Get back to compat=1.1 and refcount_width=16 +$QEMU_IMG amend -o compat=1.1 "$TEST_IMG" +print_refcount_width +# Should not work +$QEMU_IMG amend -o refcount_width=32,compat=0.10 "$TEST_IMG" +print_refcount_width + +echo +echo '=== Amend with snapshot ===' +echo + +$QEMU_IMG snapshot -c foo "$TEST_IMG" +# Just to have different refcounts across the image +$QEMU_IO -c 'write 0 16M' "$TEST_IMG" | _filter_qemu_io + +# Should not work (may work in the future by first decreasing all refcounts so +# they fit into the target range by copying them) +$QEMU_IMG amend -o refcount_width=1 "$TEST_IMG" +_check_test_img +print_refcount_width + +# Should work +$QEMU_IMG amend -o refcount_width=2 "$TEST_IMG" +_check_test_img +print_refcount_width + +echo +echo '=== Testing too many references for check ===' +echo + +IMGOPTS="$IMGOPTS,refcount_width=1" _make_test_img 64M +print_refcount_width + +# This cluster should be created at 0x50000 +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io +# Now make the second L2 entry (the L2 table should be at 0x40000) point to that +# cluster, so we have two references +poke_file "$TEST_IMG" $((0x40008)) "\x80\x00\x00\x00\x00\x05\x00\x00" + +# This should say "please use amend" +_check_test_img -r all + +# So we do that +$QEMU_IMG amend -o refcount_width=2 "$TEST_IMG" +print_refcount_width + +# And try again +_check_test_img -r all + +echo +echo '=== Multiple walks necessary during amend ===' +echo + +IMGOPTS="$IMGOPTS,refcount_width=1,cluster_size=512" _make_test_img 64k + +# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a +# single L2 table, the reftable and a single refblock. This creates 58 data +# clusters (actually, the L2 table is created here, too), so in total there are +# then 63 used clusters in the image. With a refcount width of 64, one refblock +# describes 64 clusters (512 bytes / 64 bits/entry = 64 entries), so this will +# make the first target refblock have exactly one free entry. +$QEMU_IO -c "write 0 $((58 * 512))" "$TEST_IMG" | _filter_qemu_io + +# Now change the refcount width; since the first target refblock has exactly one +# free entry, that entry will be used to store its own reference. No other +# refblocks are needed, so then the new reftable will be allocated; since the +# first target refblock is completely filled up, this will require a new +# refblock which is why the refcount width changing function will need to run +# through everything one more time until the allocations are stable. +$QEMU_IMG amend -o refcount_width=64 "$TEST_IMG" +print_refcount_width + +_check_test_img + + +# success, all done +echo '*** done' +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out new file mode 100644 index 0000000..907a05e --- /dev/null +++ b/tests/qemu-iotests/112.out @@ -0,0 +1,131 @@ +QA output created by 112 + +=== refcount_width limits === + +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 refcount_width=-1 +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Refcount width must be a power of two and may not exceed 64 bits +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 1 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 64 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 16 + +=== refcount_width and compat=0.10 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 16 +qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater) +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + +=== Snapshot limit on refcount_width=1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 1 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Could not create snapshot 'foo': -22 (Invalid argument) +Leaked cluster 6 refcount=1 reference=0 + +1 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. + +=== Snapshot limit on refcount_width=2 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 2 +wrote 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Could not create snapshot 'baz': -22 (Invalid argument) +Leaked cluster 7 refcount=1 reference=0 + +1 leaked clusters were found on the image. +This means waste of disk space, but no harm to data. + +=== Compressed clusters with refcount_width=1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 1 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. + +=== Amend from refcount_width=16 to refcount_width=1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 16 +wrote 33554432/33554432 bytes at offset 16777216 +32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. +refcount width: 1 + +=== Amend from refcount_width=1 to refcount_width=64 === + +No errors were found on the image. +refcount width: 64 + +=== Amend to compat=0.10 === + +qemu-img: compat=0.10 requires refcount_width=16 +qemu-img: Error while amending options: Operation not supported +refcount width: 64 +No errors were found on the image. +refcount width: 16 +refcount width: 16 +qemu-img: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater) +qemu-img: Error while amending options: Invalid argument +refcount width: 16 + +=== Amend with snapshot === + +wrote 16777216/16777216 bytes at offset 0 +16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Cannot decrease refcount entry width to 1 bits: Cluster at offset 0x50000 has a refcount of 2 +qemu-img: Error while amending options: Invalid argument +No errors were found on the image. +refcount width: 16 +No errors were found on the image. +refcount width: 2 + +=== Testing too many references for check === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount width: 1 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +ERROR: overflow cluster offset=0x50000 +Use qemu-img amend to increase the refcount entry width or qemu-img convert to create a clean copy if the image cannot be opened for writing + +1 errors were found on the image. +Data may be corrupted, or further writes to the image may corrupt it. +refcount width: 2 +ERROR cluster 5 refcount=1 reference=2 +Repairing cluster 5 refcount=1 reference=2 +Repairing OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=2 +Repairing OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=2 +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. + +=== Multiple walks necessary during amend === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 +wrote 29696/29696 bytes at offset 0 +29 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +refcount width: 64 +No errors were found on the image. +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 7dfe469..593f3dd 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -112,3 +112,4 @@ 107 rw auto quick 108 rw auto quick 111 rw auto quick +112 rw auto -- 1.9.3