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