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