1#!/usr/bin/env bash 2# 3# Test case for repairing qcow2 images which cannot be repaired using 4# the on-disk refcount structures 5# 6# Copyright (C) 2014 Red Hat, Inc. 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 2 of the License, or 11# (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program. If not, see <http://www.gnu.org/licenses/>. 20# 21 22# creator 23owner=mreitz@redhat.com 24 25seq="$(basename $0)" 26echo "QA output created by $seq" 27 28status=1 # failure is the default! 29 30_cleanup() 31{ 32 _cleanup_test_img 33} 34trap "_cleanup; exit \$status" 0 1 2 3 15 35 36# get standard environment, filters and checks 37. ./common.rc 38. ./common.filter 39 40# This tests qcow2-specific low-level functionality 41_supported_fmt qcow2 42_supported_proto file fuse 43_supported_os Linux 44# This test directly modifies a refblock so it relies on refcount_bits being 16; 45# and the low-level modification it performs are not tuned for external data 46# files 47_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file 48 49echo 50echo '=== Repairing an image without any refcount table ===' 51echo 52 53_make_test_img 64M 54# just write some data 55$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 56 57# refcount_table_offset 58poke_file "$TEST_IMG" $((0x30)) "\x00\x00\x00\x00\x00\x00\x00\x00" 59# refcount_table_clusters 60poke_file "$TEST_IMG" $((0x38)) "\x00\x00\x00\x00" 61 62_check_test_img -r all 63 64$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 65 66echo 67echo '=== Repairing unreferenced data cluster in new refblock area ===' 68echo 69 70_make_test_img -o 'cluster_size=512' 64M 71# Allocate the first 128 kB in the image (first refblock) 72$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io 73# should be 131072 == 0x20000 74stat -c '%s' "$TEST_IMG" 75 76# Enter a cluster at 128 kB (0x20000) 77# XXX: This should be the first free entry in the last L2 table, but we cannot 78# be certain 79poke_file "$TEST_IMG" $((0x1ccc8)) "\x80\x00\x00\x00\x00\x02\x00\x00" 80 81# Fill the cluster 82truncate -s $((0x20200)) "$TEST_IMG" 83$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'write -P 42 128k 512' \ 84 | _filter_qemu_io 85 86# The data should now appear at this guest offset 87$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 88 89# This cluster is unallocated; fix it 90_check_test_img -r all 91 92# This repair operation must have allocated a new refblock; and that refblock 93# should not overlap with the unallocated data cluster. If it does, the data 94# will be damaged, so check it. 95$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 96 97echo 98echo '=== Repairing refblock beyond the image end ===' 99echo 100 101echo 102echo '--- Otherwise clean ---' 103echo 104 105_make_test_img 64M 106# Normally, qemu doesn't create empty refblocks, so we just have to do it by 107# hand 108# XXX: This should be the entry for the second refblock 109poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 110# Mark that refblock as used 111# XXX: This should be the 17th entry (cluster 16) of the first 112# refblock 113poke_file "$TEST_IMG" $((0x20020)) "\x00\x01" 114_check_test_img -r all 115 116echo 117echo '--- Refblock is unallocated ---' 118echo 119 120_make_test_img 64M 121poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 122_check_test_img -r all 123 124echo 125echo '--- Signed overflow after the refblock ---' 126echo 127 128_make_test_img 64M 129poke_file "$TEST_IMG" $((0x10008)) "\x7f\xff\xff\xff\xff\xff\x00\x00" 130_check_test_img -r all 131 132echo 133echo '--- Unsigned overflow after the refblock ---' 134echo 135 136_make_test_img 64M 137poke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00" 138_check_test_img -r all 139 140# success, all done 141echo '*** done' 142rm -f $seq.full 143status=0 144