9ae3a8
From de5dd97bab0923fdd8cd4ffebbbf3c031446030c Mon Sep 17 00:00:00 2001
9ae3a8
From: Max Reitz <mreitz@redhat.com>
9ae3a8
Date: Sat, 13 Jun 2015 16:22:25 +0200
9ae3a8
Subject: [PATCH 31/42] iotests: Add test for potentially damaging repairs
9ae3a8
9ae3a8
Message-id: <1434212556-3927-32-git-send-email-mreitz@redhat.com>
9ae3a8
Patchwork-id: 66050
9ae3a8
O-Subject: [RHEL-7.2 qemu-kvm PATCH 31/42] iotests: Add test for potentially damaging repairs
9ae3a8
Bugzilla: 1129893
9ae3a8
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
BZ: 1129893
9ae3a8
9ae3a8
There are certain cases where repairing a qcow2 image might actually
9ae3a8
damage it further (or rather, where repairing it has in fact damaged it
9ae3a8
further with the old qcow2 check implementation). This should not
9ae3a8
happen, so add a test for these cases.
9ae3a8
9ae3a8
Furthermore, the repair function now repairs refblocks beyond the image
9ae3a8
end by resizing the image accordingly. Add several tests for this as
9ae3a8
well.
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit 234764eed1aab56a657a161e9a0c65730442e6f8)
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	tests/qemu-iotests/group
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
---
9ae3a8
 tests/qemu-iotests/108     | 141 +++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 tests/qemu-iotests/108.out | 110 +++++++++++++++++++++++++++++++++++
9ae3a8
 tests/qemu-iotests/group   |   1 +
9ae3a8
 3 files changed, 252 insertions(+)
9ae3a8
 create mode 100755 tests/qemu-iotests/108
9ae3a8
 create mode 100644 tests/qemu-iotests/108.out
9ae3a8
9ae3a8
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
9ae3a8
new file mode 100755
9ae3a8
index 0000000..12fc92a
9ae3a8
--- /dev/null
9ae3a8
+++ b/tests/qemu-iotests/108
9ae3a8
@@ -0,0 +1,141 @@
9ae3a8
+#!/bin/bash
9ae3a8
+#
9ae3a8
+# Test case for repairing qcow2 images which cannot be repaired using
9ae3a8
+# the on-disk refcount structures
9ae3a8
+#
9ae3a8
+# Copyright (C) 2014 Red Hat, Inc.
9ae3a8
+#
9ae3a8
+# This program is free software; you can redistribute it and/or modify
9ae3a8
+# it under the terms of the GNU General Public License as published by
9ae3a8
+# the Free Software Foundation; either version 2 of the License, or
9ae3a8
+# (at your option) any later version.
9ae3a8
+#
9ae3a8
+# This program is distributed in the hope that it will be useful,
9ae3a8
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
9ae3a8
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9ae3a8
+# GNU General Public License for more details.
9ae3a8
+#
9ae3a8
+# You should have received a copy of the GNU General Public License
9ae3a8
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
9ae3a8
+#
9ae3a8
+
9ae3a8
+# creator
9ae3a8
+owner=mreitz@redhat.com
9ae3a8
+
9ae3a8
+seq="$(basename $0)"
9ae3a8
+echo "QA output created by $seq"
9ae3a8
+
9ae3a8
+here="$PWD"
9ae3a8
+tmp=/tmp/$$
9ae3a8
+status=1	# failure is the default!
9ae3a8
+
9ae3a8
+_cleanup()
9ae3a8
+{
9ae3a8
+	_cleanup_test_img
9ae3a8
+}
9ae3a8
+trap "_cleanup; exit \$status" 0 1 2 3 15
9ae3a8
+
9ae3a8
+# get standard environment, filters and checks
9ae3a8
+. ./common.rc
9ae3a8
+. ./common.filter
9ae3a8
+
9ae3a8
+# This tests qocw2-specific low-level functionality
9ae3a8
+_supported_fmt qcow2
9ae3a8
+_supported_proto file
9ae3a8
+_supported_os Linux
9ae3a8
+
9ae3a8
+echo
9ae3a8
+echo '=== Repairing an image without any refcount table ==='
9ae3a8
+echo
9ae3a8
+
9ae3a8
+_make_test_img 64M
9ae3a8
+# just write some data
9ae3a8
+$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
9ae3a8
+
9ae3a8
+# refcount_table_offset
9ae3a8
+poke_file "$TEST_IMG" $((0x30)) "\x00\x00\x00\x00\x00\x00\x00\x00"
9ae3a8
+# refcount_table_clusters
9ae3a8
+poke_file "$TEST_IMG" $((0x38)) "\x00\x00\x00\x00"
9ae3a8
+
9ae3a8
+_check_test_img -r all
9ae3a8
+
9ae3a8
+$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
9ae3a8
+
9ae3a8
+echo
9ae3a8
+echo '=== Repairing unreferenced data cluster in new refblock area ==='
9ae3a8
+echo
9ae3a8
+
9ae3a8
+IMGOPTS='cluster_size=512' _make_test_img 64M
9ae3a8
+# Allocate the first 128 kB in the image (first refblock)
9ae3a8
+$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io
9ae3a8
+# should be 131072 == 0x20000
9ae3a8
+stat -c '%s' "$TEST_IMG"
9ae3a8
+
9ae3a8
+# Enter a cluster at 128 kB (0x20000)
9ae3a8
+# XXX: This should be the first free entry in the last L2 table, but we cannot
9ae3a8
+# be certain
9ae3a8
+poke_file "$TEST_IMG" $((0x1ccc8)) "\x80\x00\x00\x00\x00\x02\x00\x00"
9ae3a8
+
9ae3a8
+# Fill the cluster
9ae3a8
+truncate -s $((0x20200)) "$TEST_IMG"
9ae3a8
+$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'write -P 42 128k 512' \
9ae3a8
+    | _filter_qemu_io
9ae3a8
+
9ae3a8
+# The data should now appear at this guest offset
9ae3a8
+$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io
9ae3a8
+
9ae3a8
+# This cluster is unallocated; fix it
9ae3a8
+_check_test_img -r all
9ae3a8
+
9ae3a8
+# This repair operation must have allocated a new refblock; and that refblock
9ae3a8
+# should not overlap with the unallocated data cluster. If it does, the data
9ae3a8
+# will be damaged, so check it.
9ae3a8
+$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io
9ae3a8
+
9ae3a8
+echo
9ae3a8
+echo '=== Repairing refblock beyond the image end ==='
9ae3a8
+echo
9ae3a8
+
9ae3a8
+echo
9ae3a8
+echo '--- Otherwise clean ---'
9ae3a8
+echo
9ae3a8
+
9ae3a8
+_make_test_img 64M
9ae3a8
+# Normally, qemu doesn't create empty refblocks, so we just have to do it by
9ae3a8
+# hand
9ae3a8
+# XXX: This should be the entry for the second refblock
9ae3a8
+poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00"
9ae3a8
+# Mark that refblock as used
9ae3a8
+# XXX: This should be the 17th entry (cluster 16) of the first
9ae3a8
+# refblock
9ae3a8
+poke_file "$TEST_IMG" $((0x20020)) "\x00\x01"
9ae3a8
+_check_test_img -r all
9ae3a8
+
9ae3a8
+echo
9ae3a8
+echo '--- Refblock is unallocated ---'
9ae3a8
+echo
9ae3a8
+
9ae3a8
+_make_test_img 64M
9ae3a8
+poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00"
9ae3a8
+_check_test_img -r all
9ae3a8
+
9ae3a8
+echo
9ae3a8
+echo '--- Signed overflow after the refblock ---'
9ae3a8
+echo
9ae3a8
+
9ae3a8
+_make_test_img 64M
9ae3a8
+poke_file "$TEST_IMG" $((0x10008)) "\x7f\xff\xff\xff\xff\xff\x00\x00"
9ae3a8
+_check_test_img -r all
9ae3a8
+
9ae3a8
+echo
9ae3a8
+echo '--- Unsigned overflow after the refblock ---'
9ae3a8
+echo
9ae3a8
+
9ae3a8
+_make_test_img 64M
9ae3a8
+poke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00"
9ae3a8
+_check_test_img -r all
9ae3a8
+
9ae3a8
+# success, all done
9ae3a8
+echo '*** done'
9ae3a8
+rm -f $seq.full
9ae3a8
+status=0
9ae3a8
diff --git a/tests/qemu-iotests/108.out b/tests/qemu-iotests/108.out
9ae3a8
new file mode 100644
9ae3a8
index 0000000..824d5cf
9ae3a8
--- /dev/null
9ae3a8
+++ b/tests/qemu-iotests/108.out
9ae3a8
@@ -0,0 +1,110 @@
9ae3a8
+QA output created by 108
9ae3a8
+
9ae3a8
+=== Repairing an image without any refcount table ===
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
+wrote 65536/65536 bytes at offset 0
9ae3a8
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
9ae3a8
+ERROR cluster 0 refcount=0 reference=1
9ae3a8
+ERROR cluster 3 refcount=0 reference=1
9ae3a8
+ERROR cluster 4 refcount=0 reference=1
9ae3a8
+ERROR cluster 5 refcount=0 reference=1
9ae3a8
+Rebuilding refcount structure
9ae3a8
+The following inconsistencies were found and repaired:
9ae3a8
+
9ae3a8
+    0 leaked clusters
9ae3a8
+    4 corruptions
9ae3a8
+
9ae3a8
+Double checking the fixed image now...
9ae3a8
+No errors were found on the image.
9ae3a8
+read 65536/65536 bytes at offset 0
9ae3a8
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
9ae3a8
+
9ae3a8
+=== Repairing unreferenced data cluster in new refblock area ===
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
+wrote 111104/111104 bytes at offset 0
9ae3a8
+108.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
9ae3a8
+131072
9ae3a8
+wrote 512/512 bytes at offset 131072
9ae3a8
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
9ae3a8
+read 512/512 bytes at offset 111104
9ae3a8
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
9ae3a8
+ERROR cluster 256 refcount=0 reference=1
9ae3a8
+Rebuilding refcount structure
9ae3a8
+Repairing cluster 1 refcount=1 reference=0
9ae3a8
+Repairing cluster 2 refcount=1 reference=0
9ae3a8
+The following inconsistencies were found and repaired:
9ae3a8
+
9ae3a8
+    0 leaked clusters
9ae3a8
+    1 corruptions
9ae3a8
+
9ae3a8
+Double checking the fixed image now...
9ae3a8
+No errors were found on the image.
9ae3a8
+read 512/512 bytes at offset 111104
9ae3a8
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
9ae3a8
+
9ae3a8
+=== Repairing refblock beyond the image end ===
9ae3a8
+
9ae3a8
+
9ae3a8
+--- Otherwise clean ---
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
+Repairing refcount block 1 is outside image
9ae3a8
+The following inconsistencies were found and repaired:
9ae3a8
+
9ae3a8
+    0 leaked clusters
9ae3a8
+    1 corruptions
9ae3a8
+
9ae3a8
+Double checking the fixed image now...
9ae3a8
+No errors were found on the image.
9ae3a8
+
9ae3a8
+--- Refblock is unallocated ---
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
+Repairing refcount block 1 is outside image
9ae3a8
+ERROR cluster 16 refcount=0 reference=1
9ae3a8
+Rebuilding refcount structure
9ae3a8
+Repairing cluster 1 refcount=1 reference=0
9ae3a8
+Repairing cluster 2 refcount=1 reference=0
9ae3a8
+Repairing cluster 16 refcount=1 reference=0
9ae3a8
+The following inconsistencies were found and repaired:
9ae3a8
+
9ae3a8
+    0 leaked clusters
9ae3a8
+    2 corruptions
9ae3a8
+
9ae3a8
+Double checking the fixed image now...
9ae3a8
+No errors were found on the image.
9ae3a8
+
9ae3a8
+--- Signed overflow after the refblock ---
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
+Repairing refcount block 1 is outside image
9ae3a8
+ERROR could not resize image: Invalid argument
9ae3a8
+Rebuilding refcount structure
9ae3a8
+Repairing cluster 1 refcount=1 reference=0
9ae3a8
+Repairing cluster 2 refcount=1 reference=0
9ae3a8
+The following inconsistencies were found and repaired:
9ae3a8
+
9ae3a8
+    0 leaked clusters
9ae3a8
+    1 corruptions
9ae3a8
+
9ae3a8
+Double checking the fixed image now...
9ae3a8
+No errors were found on the image.
9ae3a8
+
9ae3a8
+--- Unsigned overflow after the refblock ---
9ae3a8
+
9ae3a8
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
9ae3a8
+Repairing refcount block 1 is outside image
9ae3a8
+ERROR could not resize image: Invalid argument
9ae3a8
+Rebuilding refcount structure
9ae3a8
+Repairing cluster 1 refcount=1 reference=0
9ae3a8
+Repairing cluster 2 refcount=1 reference=0
9ae3a8
+The following inconsistencies were found and repaired:
9ae3a8
+
9ae3a8
+    0 leaked clusters
9ae3a8
+    1 corruptions
9ae3a8
+
9ae3a8
+Double checking the fixed image now...
9ae3a8
+No errors were found on the image.
9ae3a8
+*** done
9ae3a8
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
9ae3a8
index dd3c5fe..695ab02 100644
9ae3a8
--- a/tests/qemu-iotests/group
9ae3a8
+++ b/tests/qemu-iotests/group
9ae3a8
@@ -87,3 +87,4 @@
9ae3a8
 092 rw auto quick
9ae3a8
 105 rw auto quick
9ae3a8
 107 rw auto quick
9ae3a8
+108 rw auto quick
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8