111a82d14SPhilippe Mathieu-Daudé#!/usr/bin/env bash 2234764eeSMax Reitz# 3234764eeSMax Reitz# Test case for repairing qcow2 images which cannot be repaired using 4234764eeSMax Reitz# the on-disk refcount structures 5234764eeSMax Reitz# 6234764eeSMax Reitz# Copyright (C) 2014 Red Hat, Inc. 7234764eeSMax Reitz# 8234764eeSMax Reitz# This program is free software; you can redistribute it and/or modify 9234764eeSMax Reitz# it under the terms of the GNU General Public License as published by 10234764eeSMax Reitz# the Free Software Foundation; either version 2 of the License, or 11234764eeSMax Reitz# (at your option) any later version. 12234764eeSMax Reitz# 13234764eeSMax Reitz# This program is distributed in the hope that it will be useful, 14234764eeSMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of 15234764eeSMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16234764eeSMax Reitz# GNU General Public License for more details. 17234764eeSMax Reitz# 18234764eeSMax Reitz# You should have received a copy of the GNU General Public License 19234764eeSMax Reitz# along with this program. If not, see <http://www.gnu.org/licenses/>. 20234764eeSMax Reitz# 21234764eeSMax Reitz 22234764eeSMax Reitz# creator 23234764eeSMax Reitzowner=mreitz@redhat.com 24234764eeSMax Reitz 25234764eeSMax Reitzseq="$(basename $0)" 26234764eeSMax Reitzecho "QA output created by $seq" 27234764eeSMax Reitz 28234764eeSMax Reitzstatus=1 # failure is the default! 29234764eeSMax Reitz 30234764eeSMax Reitz_cleanup() 31234764eeSMax Reitz{ 32234764eeSMax Reitz _cleanup_test_img 33234764eeSMax Reitz} 34234764eeSMax Reitztrap "_cleanup; exit \$status" 0 1 2 3 15 35234764eeSMax Reitz 36234764eeSMax Reitz# get standard environment, filters and checks 37234764eeSMax Reitz. ./common.rc 38234764eeSMax Reitz. ./common.filter 39234764eeSMax Reitz 40e696f335SMax Reitz# This tests qcow2-specific low-level functionality 41234764eeSMax Reitz_supported_fmt qcow2 42*57284d2aSMax Reitz_supported_proto file fuse 43234764eeSMax Reitz_supported_os Linux 443be2024aSMax Reitz# This test directly modifies a refblock so it relies on refcount_bits being 16; 453be2024aSMax Reitz# and the low-level modification it performs are not tuned for external data 463be2024aSMax Reitz# files 473be2024aSMax Reitz_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file 48234764eeSMax Reitz 49234764eeSMax Reitzecho 50234764eeSMax Reitzecho '=== Repairing an image without any refcount table ===' 51234764eeSMax Reitzecho 52234764eeSMax Reitz 53234764eeSMax Reitz_make_test_img 64M 54234764eeSMax Reitz# just write some data 55234764eeSMax Reitz$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 56234764eeSMax Reitz 57234764eeSMax Reitz# refcount_table_offset 58234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x30)) "\x00\x00\x00\x00\x00\x00\x00\x00" 59234764eeSMax Reitz# refcount_table_clusters 60234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x38)) "\x00\x00\x00\x00" 61234764eeSMax Reitz 62234764eeSMax Reitz_check_test_img -r all 63234764eeSMax Reitz 64234764eeSMax Reitz$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 65234764eeSMax Reitz 66234764eeSMax Reitzecho 67234764eeSMax Reitzecho '=== Repairing unreferenced data cluster in new refblock area ===' 68234764eeSMax Reitzecho 69234764eeSMax Reitz 70407fb56aSMax Reitz_make_test_img -o 'cluster_size=512' 64M 71234764eeSMax Reitz# Allocate the first 128 kB in the image (first refblock) 72234764eeSMax Reitz$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io 73234764eeSMax Reitz# should be 131072 == 0x20000 74234764eeSMax Reitzstat -c '%s' "$TEST_IMG" 75234764eeSMax Reitz 76234764eeSMax Reitz# Enter a cluster at 128 kB (0x20000) 77234764eeSMax Reitz# XXX: This should be the first free entry in the last L2 table, but we cannot 78234764eeSMax Reitz# be certain 79234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x1ccc8)) "\x80\x00\x00\x00\x00\x02\x00\x00" 80234764eeSMax Reitz 81234764eeSMax Reitz# Fill the cluster 82234764eeSMax Reitztruncate -s $((0x20200)) "$TEST_IMG" 83234764eeSMax Reitz$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'write -P 42 128k 512' \ 84234764eeSMax Reitz | _filter_qemu_io 85234764eeSMax Reitz 86234764eeSMax Reitz# The data should now appear at this guest offset 87234764eeSMax Reitz$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 88234764eeSMax Reitz 89234764eeSMax Reitz# This cluster is unallocated; fix it 90234764eeSMax Reitz_check_test_img -r all 91234764eeSMax Reitz 92234764eeSMax Reitz# This repair operation must have allocated a new refblock; and that refblock 93234764eeSMax Reitz# should not overlap with the unallocated data cluster. If it does, the data 94234764eeSMax Reitz# will be damaged, so check it. 95234764eeSMax Reitz$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 96234764eeSMax Reitz 97234764eeSMax Reitzecho 98234764eeSMax Reitzecho '=== Repairing refblock beyond the image end ===' 99234764eeSMax Reitzecho 100234764eeSMax Reitz 101234764eeSMax Reitzecho 102234764eeSMax Reitzecho '--- Otherwise clean ---' 103234764eeSMax Reitzecho 104234764eeSMax Reitz 105234764eeSMax Reitz_make_test_img 64M 106234764eeSMax Reitz# Normally, qemu doesn't create empty refblocks, so we just have to do it by 107234764eeSMax Reitz# hand 108234764eeSMax Reitz# XXX: This should be the entry for the second refblock 109234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 110234764eeSMax Reitz# Mark that refblock as used 111234764eeSMax Reitz# XXX: This should be the 17th entry (cluster 16) of the first 112234764eeSMax Reitz# refblock 113234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x20020)) "\x00\x01" 114234764eeSMax Reitz_check_test_img -r all 115234764eeSMax Reitz 116234764eeSMax Reitzecho 117234764eeSMax Reitzecho '--- Refblock is unallocated ---' 118234764eeSMax Reitzecho 119234764eeSMax Reitz 120234764eeSMax Reitz_make_test_img 64M 121234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 122234764eeSMax Reitz_check_test_img -r all 123234764eeSMax Reitz 124234764eeSMax Reitzecho 125234764eeSMax Reitzecho '--- Signed overflow after the refblock ---' 126234764eeSMax Reitzecho 127234764eeSMax Reitz 128234764eeSMax Reitz_make_test_img 64M 129234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\x7f\xff\xff\xff\xff\xff\x00\x00" 130234764eeSMax Reitz_check_test_img -r all 131234764eeSMax Reitz 132234764eeSMax Reitzecho 133234764eeSMax Reitzecho '--- Unsigned overflow after the refblock ---' 134234764eeSMax Reitzecho 135234764eeSMax Reitz 136234764eeSMax Reitz_make_test_img 64M 137234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00" 138234764eeSMax Reitz_check_test_img -r all 139234764eeSMax Reitz 140234764eeSMax Reitz# success, all done 141234764eeSMax Reitzecho '*** done' 142234764eeSMax Reitzrm -f $seq.full 143234764eeSMax Reitzstatus=0 144