1#!/bin/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 28here="$PWD" 29tmp=/tmp/$$ 30status=1 # failure is the default! 31 32_cleanup() 33{ 34 _cleanup_test_img 35} 36trap "_cleanup; exit \$status" 0 1 2 3 15 37 38# get standard environment, filters and checks 39. ./common.rc 40. ./common.filter 41 42# This tests qocw2-specific low-level functionality 43_supported_fmt qcow2 44_supported_proto file 45_supported_os Linux 46 47echo 48echo '=== Repairing an image without any refcount table ===' 49echo 50 51_make_test_img 64M 52# just write some data 53$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 54 55# refcount_table_offset 56poke_file "$TEST_IMG" $((0x30)) "\x00\x00\x00\x00\x00\x00\x00\x00" 57# refcount_table_clusters 58poke_file "$TEST_IMG" $((0x38)) "\x00\x00\x00\x00" 59 60_check_test_img -r all 61 62$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 63 64echo 65echo '=== Repairing unreferenced data cluster in new refblock area ===' 66echo 67 68IMGOPTS='cluster_size=512' _make_test_img 64M 69# Allocate the first 128 kB in the image (first refblock) 70$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io 71# should be 131072 == 0x20000 72stat -c '%s' "$TEST_IMG" 73 74# Enter a cluster at 128 kB (0x20000) 75# XXX: This should be the first free entry in the last L2 table, but we cannot 76# be certain 77poke_file "$TEST_IMG" $((0x1ccc8)) "\x80\x00\x00\x00\x00\x02\x00\x00" 78 79# Fill the cluster 80truncate -s $((0x20200)) "$TEST_IMG" 81$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'write -P 42 128k 512' \ 82 | _filter_qemu_io 83 84# The data should now appear at this guest offset 85$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 86 87# This cluster is unallocated; fix it 88_check_test_img -r all 89 90# This repair operation must have allocated a new refblock; and that refblock 91# should not overlap with the unallocated data cluster. If it does, the data 92# will be damaged, so check it. 93$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 94 95echo 96echo '=== Repairing refblock beyond the image end ===' 97echo 98 99echo 100echo '--- Otherwise clean ---' 101echo 102 103_make_test_img 64M 104# Normally, qemu doesn't create empty refblocks, so we just have to do it by 105# hand 106# XXX: This should be the entry for the second refblock 107poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 108# Mark that refblock as used 109# XXX: This should be the 17th entry (cluster 16) of the first 110# refblock 111poke_file "$TEST_IMG" $((0x20020)) "\x00\x01" 112_check_test_img -r all 113 114echo 115echo '--- Refblock is unallocated ---' 116echo 117 118_make_test_img 64M 119poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 120_check_test_img -r all 121 122echo 123echo '--- Signed overflow after the refblock ---' 124echo 125 126_make_test_img 64M 127poke_file "$TEST_IMG" $((0x10008)) "\x7f\xff\xff\xff\xff\xff\x00\x00" 128_check_test_img -r all 129 130echo 131echo '--- Unsigned overflow after the refblock ---' 132echo 133 134_make_test_img 64M 135poke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00" 136_check_test_img -r all 137 138# success, all done 139echo '*** done' 140rm -f $seq.full 141status=0 142