111a82d14SPhilippe Mathieu-Daudé#!/usr/bin/env bash 29dd003a9SVladimir 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 2442a5009dSJohn Snowowner=hreitz@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 349ffd6d64SHanna Reitz if [ -f "$TEST_DIR/qsd.pid" ]; then 359ffd6d64SHanna Reitz qsd_pid=$(cat "$TEST_DIR/qsd.pid") 369ffd6d64SHanna Reitz kill -KILL "$qsd_pid" 379ffd6d64SHanna Reitz fusermount -u "$TEST_DIR/fuse-export" &>/dev/null 389ffd6d64SHanna Reitz fi 399ffd6d64SHanna Reitz rm -f "$TEST_DIR/fuse-export" 40234764eeSMax Reitz} 41234764eeSMax Reitztrap "_cleanup; exit \$status" 0 1 2 3 15 42234764eeSMax Reitz 43234764eeSMax Reitz# get standard environment, filters and checks 44234764eeSMax Reitz. ./common.rc 45234764eeSMax Reitz. ./common.filter 469ffd6d64SHanna Reitz. ./common.qemu 47234764eeSMax Reitz 48e696f335SMax Reitz# This tests qcow2-specific low-level functionality 49234764eeSMax Reitz_supported_fmt qcow2 5057284d2aSMax Reitz_supported_proto file fuse 51234764eeSMax Reitz_supported_os Linux 523be2024aSMax Reitz# This test directly modifies a refblock so it relies on refcount_bits being 16; 533be2024aSMax Reitz# and the low-level modification it performs are not tuned for external data 543be2024aSMax Reitz# files 553be2024aSMax Reitz_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file 56234764eeSMax Reitz 579ffd6d64SHanna Reitz# This test either needs sudo -n losetup or FUSE exports to work 589ffd6d64SHanna Reitzif sudo -n losetup &>/dev/null; then 599ffd6d64SHanna Reitz loopdev=true 609ffd6d64SHanna Reitzelse 619ffd6d64SHanna Reitz loopdev=false 629ffd6d64SHanna Reitz 63*92529251SJohn Snow # Check for usable FUSE in the host environment: 64*92529251SJohn Snow if test ! -c "/dev/fuse"; then 65*92529251SJohn Snow _notrun 'No passwordless sudo nor usable /dev/fuse' 66*92529251SJohn Snow fi 67*92529251SJohn Snow 689ffd6d64SHanna Reitz # QSD --export fuse will either yield "Parameter 'id' is missing" 699ffd6d64SHanna Reitz # or "Invalid parameter 'fuse'", depending on whether there is 709ffd6d64SHanna Reitz # FUSE support or not. 719ffd6d64SHanna Reitz error=$($QSD --export fuse 2>&1) 729ffd6d64SHanna Reitz if [[ $error = *"'fuse'"* ]]; then 739ffd6d64SHanna Reitz _notrun 'Passwordless sudo for losetup or FUSE support required, but' \ 749ffd6d64SHanna Reitz 'neither is available' 759ffd6d64SHanna Reitz fi 769ffd6d64SHanna Reitzfi 779ffd6d64SHanna Reitz 78234764eeSMax Reitzecho 79234764eeSMax Reitzecho '=== Repairing an image without any refcount table ===' 80234764eeSMax Reitzecho 81234764eeSMax Reitz 82234764eeSMax Reitz_make_test_img 64M 83234764eeSMax Reitz# just write some data 84234764eeSMax Reitz$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 85234764eeSMax Reitz 86234764eeSMax Reitz# refcount_table_offset 87234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x30)) "\x00\x00\x00\x00\x00\x00\x00\x00" 88234764eeSMax Reitz# refcount_table_clusters 89234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x38)) "\x00\x00\x00\x00" 90234764eeSMax Reitz 91234764eeSMax Reitz_check_test_img -r all 92234764eeSMax Reitz 93234764eeSMax Reitz$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io 94234764eeSMax Reitz 95234764eeSMax Reitzecho 96234764eeSMax Reitzecho '=== Repairing unreferenced data cluster in new refblock area ===' 97234764eeSMax Reitzecho 98234764eeSMax Reitz 99407fb56aSMax Reitz_make_test_img -o 'cluster_size=512' 64M 100234764eeSMax Reitz# Allocate the first 128 kB in the image (first refblock) 101234764eeSMax Reitz$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io 102234764eeSMax Reitz# should be 131072 == 0x20000 103234764eeSMax Reitzstat -c '%s' "$TEST_IMG" 104234764eeSMax Reitz 105234764eeSMax Reitz# Enter a cluster at 128 kB (0x20000) 106234764eeSMax Reitz# XXX: This should be the first free entry in the last L2 table, but we cannot 107234764eeSMax Reitz# be certain 108234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x1ccc8)) "\x80\x00\x00\x00\x00\x02\x00\x00" 109234764eeSMax Reitz 110234764eeSMax Reitz# Fill the cluster 111234764eeSMax Reitztruncate -s $((0x20200)) "$TEST_IMG" 112234764eeSMax Reitz$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'write -P 42 128k 512' \ 113234764eeSMax Reitz | _filter_qemu_io 114234764eeSMax Reitz 115234764eeSMax Reitz# The data should now appear at this guest offset 116234764eeSMax Reitz$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 117234764eeSMax Reitz 118234764eeSMax Reitz# This cluster is unallocated; fix it 119234764eeSMax Reitz_check_test_img -r all 120234764eeSMax Reitz 121234764eeSMax Reitz# This repair operation must have allocated a new refblock; and that refblock 122234764eeSMax Reitz# should not overlap with the unallocated data cluster. If it does, the data 123234764eeSMax Reitz# will be damaged, so check it. 124234764eeSMax Reitz$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io 125234764eeSMax Reitz 126234764eeSMax Reitzecho 127234764eeSMax Reitzecho '=== Repairing refblock beyond the image end ===' 128234764eeSMax Reitzecho 129234764eeSMax Reitz 130234764eeSMax Reitzecho 131234764eeSMax Reitzecho '--- Otherwise clean ---' 132234764eeSMax Reitzecho 133234764eeSMax Reitz 134234764eeSMax Reitz_make_test_img 64M 135234764eeSMax Reitz# Normally, qemu doesn't create empty refblocks, so we just have to do it by 136234764eeSMax Reitz# hand 137234764eeSMax Reitz# XXX: This should be the entry for the second refblock 138234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 139234764eeSMax Reitz# Mark that refblock as used 140234764eeSMax Reitz# XXX: This should be the 17th entry (cluster 16) of the first 141234764eeSMax Reitz# refblock 142234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x20020)) "\x00\x01" 143234764eeSMax Reitz_check_test_img -r all 144234764eeSMax Reitz 145234764eeSMax Reitzecho 146234764eeSMax Reitzecho '--- Refblock is unallocated ---' 147234764eeSMax Reitzecho 148234764eeSMax Reitz 149234764eeSMax Reitz_make_test_img 64M 150234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" 151234764eeSMax Reitz_check_test_img -r all 152234764eeSMax Reitz 153234764eeSMax Reitzecho 154234764eeSMax Reitzecho '--- Signed overflow after the refblock ---' 155234764eeSMax Reitzecho 156234764eeSMax Reitz 157234764eeSMax Reitz_make_test_img 64M 158234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\x7f\xff\xff\xff\xff\xff\x00\x00" 159234764eeSMax Reitz_check_test_img -r all 160234764eeSMax Reitz 161234764eeSMax Reitzecho 162234764eeSMax Reitzecho '--- Unsigned overflow after the refblock ---' 163234764eeSMax Reitzecho 164234764eeSMax Reitz 165234764eeSMax Reitz_make_test_img 64M 166234764eeSMax Reitzpoke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00" 167234764eeSMax Reitz_check_test_img -r all 168234764eeSMax Reitz 1699ffd6d64SHanna Reitzecho 1709ffd6d64SHanna Reitzecho '=== Check rebuilt reftable location ===' 1719ffd6d64SHanna Reitz 1729ffd6d64SHanna Reitz# In an earlier version of the refcount rebuild algorithm, the 1739ffd6d64SHanna Reitz# reftable was generally placed at the image end (unless something was 1749ffd6d64SHanna Reitz# allocated in the area covered by the refblock right before the image 1759ffd6d64SHanna Reitz# file end, then we would try to place the reftable in that refblock). 1769ffd6d64SHanna Reitz# This was later changed so the reftable would be placed in the 1779ffd6d64SHanna Reitz# earliest possible location. Test this. 1789ffd6d64SHanna Reitz 1799ffd6d64SHanna Reitzecho 1809ffd6d64SHanna Reitzecho '--- Does the image size increase? ---' 1819ffd6d64SHanna Reitzecho 1829ffd6d64SHanna Reitz 1839ffd6d64SHanna Reitz# First test: Just create some image, write some data to it, and 1849ffd6d64SHanna Reitz# resize it so there is free space at the end of the image (enough 1859ffd6d64SHanna Reitz# that it spans at least one full refblock, which for cluster_size=512 1869ffd6d64SHanna Reitz# images, spans 128k). With the old algorithm, the reftable would 1879ffd6d64SHanna Reitz# have then been placed at the end of the image file, but with the new 1889ffd6d64SHanna Reitz# one, it will be put in that free space. 1899ffd6d64SHanna Reitz# We want to check whether the size of the image file increases due to 1909ffd6d64SHanna Reitz# rebuilding the refcount structures (it should not). 1919ffd6d64SHanna Reitz 1929ffd6d64SHanna Reitz_make_test_img -o 'cluster_size=512' 1M 1939ffd6d64SHanna Reitz# Write something 1949ffd6d64SHanna Reitz$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io 1959ffd6d64SHanna Reitz 1969ffd6d64SHanna Reitz# Add free space 1979ffd6d64SHanna Reitzfile_len=$(stat -c '%s' "$TEST_IMG") 1989ffd6d64SHanna Reitztruncate -s $((file_len + 256 * 1024)) "$TEST_IMG" 1999ffd6d64SHanna Reitz 2009ffd6d64SHanna Reitz# Corrupt the image by saying the image header was not allocated 2019ffd6d64SHanna Reitzrt_offset=$(peek_file_be "$TEST_IMG" 48 8) 2029ffd6d64SHanna Reitzrb_offset=$(peek_file_be "$TEST_IMG" $rt_offset 8) 2039ffd6d64SHanna Reitzpoke_file "$TEST_IMG" $rb_offset "\x00\x00" 2049ffd6d64SHanna Reitz 2059ffd6d64SHanna Reitz# Check whether rebuilding the refcount structures increases the image 2069ffd6d64SHanna Reitz# file size 2079ffd6d64SHanna Reitzfile_len=$(stat -c '%s' "$TEST_IMG") 2089ffd6d64SHanna Reitzecho 2099ffd6d64SHanna Reitz# The only leaks there can be are the old refcount structures that are 2109ffd6d64SHanna Reitz# leaked during rebuilding, no need to clutter the output with them 2119ffd6d64SHanna Reitz_check_test_img -r all | grep -v '^Repairing cluster.*refcount=1 reference=0' 2129ffd6d64SHanna Reitzecho 2139ffd6d64SHanna Reitzpost_repair_file_len=$(stat -c '%s' "$TEST_IMG") 2149ffd6d64SHanna Reitz 2159ffd6d64SHanna Reitzif [[ $file_len -eq $post_repair_file_len ]]; then 2169ffd6d64SHanna Reitz echo 'OK: Image size did not change' 2179ffd6d64SHanna Reitzelse 2189ffd6d64SHanna Reitz echo 'ERROR: Image size differs' \ 2199ffd6d64SHanna Reitz "($file_len before, $post_repair_file_len after)" 2209ffd6d64SHanna Reitzfi 2219ffd6d64SHanna Reitz 2229ffd6d64SHanna Reitzecho 2239ffd6d64SHanna Reitzecho '--- Will the reftable occupy a hole specifically left for it? ---' 2249ffd6d64SHanna Reitzecho 2259ffd6d64SHanna Reitz 2269ffd6d64SHanna Reitz# Note: With cluster_size=512, every refblock covers 128k. 2279ffd6d64SHanna Reitz# The reftable covers 8M per reftable cluster. 2289ffd6d64SHanna Reitz 2299ffd6d64SHanna Reitz# Create an image that requires two reftable clusters (just because 2309ffd6d64SHanna Reitz# this is more interesting than a single-clustered reftable). 2319ffd6d64SHanna Reitz_make_test_img -o 'cluster_size=512' 9M 2329ffd6d64SHanna Reitz$QEMU_IO -c 'write 0 8M' "$TEST_IMG" | _filter_qemu_io 2339ffd6d64SHanna Reitz 2349ffd6d64SHanna Reitz# Writing 8M will have resized the reftable. Unfortunately, doing so 2359ffd6d64SHanna Reitz# will leave holes in the file, so we need to fill them up so we can 2369ffd6d64SHanna Reitz# be sure the whole file is allocated. Do that by writing 2379ffd6d64SHanna Reitz# consecutively smaller chunks starting from 8 MB, until the file 2389ffd6d64SHanna Reitz# length increases even with a chunk size of 512. Then we must have 2399ffd6d64SHanna Reitz# filled all holes. 2409ffd6d64SHanna Reitzofs=$((8 * 1024 * 1024)) 2419ffd6d64SHanna Reitzblock_len=$((16 * 1024)) 2429ffd6d64SHanna Reitzwhile [[ $block_len -ge 512 ]]; do 2439ffd6d64SHanna Reitz file_len=$(stat -c '%s' "$TEST_IMG") 2449ffd6d64SHanna Reitz while [[ $(stat -c '%s' "$TEST_IMG") -eq $file_len ]]; do 2459ffd6d64SHanna Reitz # Do not include this in the reference output, it does not 2469ffd6d64SHanna Reitz # really matter which qemu-io calls we do here exactly 2479ffd6d64SHanna Reitz $QEMU_IO -c "write $ofs $block_len" "$TEST_IMG" >/dev/null 2489ffd6d64SHanna Reitz ofs=$((ofs + block_len)) 2499ffd6d64SHanna Reitz done 2509ffd6d64SHanna Reitz block_len=$((block_len / 2)) 2519ffd6d64SHanna Reitzdone 2529ffd6d64SHanna Reitz 2539ffd6d64SHanna Reitz# Fill up to 9M (do not include this in the reference output either, 2549ffd6d64SHanna Reitz# $ofs is random for all we know) 2559ffd6d64SHanna Reitz$QEMU_IO -c "write $ofs $((9 * 1024 * 1024 - ofs))" "$TEST_IMG" >/dev/null 2569ffd6d64SHanna Reitz 2579ffd6d64SHanna Reitz# Make space as follows: 2589ffd6d64SHanna Reitz# - For the first refblock: Right at the beginning of the image (this 2599ffd6d64SHanna Reitz# refblock is placed in the first place possible), 2609ffd6d64SHanna Reitz# - For the reftable somewhere soon afterwards, still near the 2619ffd6d64SHanna Reitz# beginning of the image (i.e. covered by the first refblock); the 2629ffd6d64SHanna Reitz# reftable too is placed in the first place possible, but only after 2639ffd6d64SHanna Reitz# all refblocks have been placed) 2649ffd6d64SHanna Reitz# No space is needed for the other refblocks, because no refblock is 2659ffd6d64SHanna Reitz# put before the space it covers. In this test case, we do not mind 2669ffd6d64SHanna Reitz# if they are placed at the image file's end. 2679ffd6d64SHanna Reitz 2689ffd6d64SHanna Reitz# Before we make that space, we have to find out the host offset of 2699ffd6d64SHanna Reitz# the area that belonged to the two data clusters at guest offset 4k, 2709ffd6d64SHanna Reitz# because we expect the reftable to be placed there, and we will have 2719ffd6d64SHanna Reitz# to verify that it is. 2729ffd6d64SHanna Reitz 2739ffd6d64SHanna Reitzl1_offset=$(peek_file_be "$TEST_IMG" 40 8) 2749ffd6d64SHanna Reitzl2_offset=$(peek_file_be "$TEST_IMG" $l1_offset 8) 2759ffd6d64SHanna Reitzl2_offset=$((l2_offset & 0x00fffffffffffe00)) 2769ffd6d64SHanna Reitzdata_4k_offset=$(peek_file_be "$TEST_IMG" \ 2779ffd6d64SHanna Reitz $((l2_offset + 4096 / 512 * 8)) 8) 2789ffd6d64SHanna Reitzdata_4k_offset=$((data_4k_offset & 0x00fffffffffffe00)) 2799ffd6d64SHanna Reitz 2809ffd6d64SHanna Reitz$QEMU_IO -c "discard 0 512" -c "discard 4k 1k" "$TEST_IMG" | _filter_qemu_io 2819ffd6d64SHanna Reitz 2829ffd6d64SHanna Reitz# Corrupt the image by saying the image header was not allocated 2839ffd6d64SHanna Reitzrt_offset=$(peek_file_be "$TEST_IMG" 48 8) 2849ffd6d64SHanna Reitzrb_offset=$(peek_file_be "$TEST_IMG" $rt_offset 8) 2859ffd6d64SHanna Reitzpoke_file "$TEST_IMG" $rb_offset "\x00\x00" 2869ffd6d64SHanna Reitz 2879ffd6d64SHanna Reitzecho 2889ffd6d64SHanna Reitz# The only leaks there can be are the old refcount structures that are 2899ffd6d64SHanna Reitz# leaked during rebuilding, no need to clutter the output with them 2909ffd6d64SHanna Reitz_check_test_img -r all | grep -v '^Repairing cluster.*refcount=1 reference=0' 2919ffd6d64SHanna Reitzecho 2929ffd6d64SHanna Reitz 2939ffd6d64SHanna Reitz# Check whether the reftable was put where we expected 2949ffd6d64SHanna Reitzrt_offset=$(peek_file_be "$TEST_IMG" 48 8) 2959ffd6d64SHanna Reitzif [[ $rt_offset -eq $data_4k_offset ]]; then 2969ffd6d64SHanna Reitz echo 'OK: Reftable is where we expect it' 2979ffd6d64SHanna Reitzelse 2989ffd6d64SHanna Reitz echo "ERROR: Reftable is at $rt_offset, but was expected at $data_4k_offset" 2999ffd6d64SHanna Reitzfi 3009ffd6d64SHanna Reitz 3019ffd6d64SHanna Reitzecho 3029ffd6d64SHanna Reitzecho '--- Rebuilding refcount structures on block devices ---' 3039ffd6d64SHanna Reitzecho 3049ffd6d64SHanna Reitz 3059ffd6d64SHanna Reitz# A block device cannot really grow, at least not during qemu-img 3069ffd6d64SHanna Reitz# check. As mentioned in the above cases, rebuilding the refcount 3079ffd6d64SHanna Reitz# structure may lead to new refcount structures being written after 3089ffd6d64SHanna Reitz# the end of the image, and in the past that happened even if there 3099ffd6d64SHanna Reitz# was more than sufficient space in the image. Such post-EOF writes 3109ffd6d64SHanna Reitz# will not work on block devices, so test that the new algorithm 3119ffd6d64SHanna Reitz# avoids it. 3129ffd6d64SHanna Reitz 3139ffd6d64SHanna Reitz# If we have passwordless sudo and losetup, we can use those to create 3149ffd6d64SHanna Reitz# a block device. Otherwise, we can resort to qemu's FUSE export to 3159ffd6d64SHanna Reitz# create a file that isn't growable, which effectively tests the same 3169ffd6d64SHanna Reitz# thing. 3179ffd6d64SHanna Reitz 3189ffd6d64SHanna Reitz_cleanup_test_img 3199ffd6d64SHanna Reitztruncate -s $((64 * 1024 * 1024)) "$TEST_IMG" 3209ffd6d64SHanna Reitz 3219ffd6d64SHanna Reitzif $loopdev; then 3229ffd6d64SHanna Reitz export_mp=$(sudo -n losetup --show -f "$TEST_IMG") 3239ffd6d64SHanna Reitz export_mp_driver=host_device 3249ffd6d64SHanna Reitz sudo -n chmod go+rw "$export_mp" 3259ffd6d64SHanna Reitzelse 3269ffd6d64SHanna Reitz # Create non-growable FUSE export that is a bit like an empty 3279ffd6d64SHanna Reitz # block device 3289ffd6d64SHanna Reitz export_mp="$TEST_DIR/fuse-export" 3299ffd6d64SHanna Reitz export_mp_driver=file 3309ffd6d64SHanna Reitz touch "$export_mp" 3319ffd6d64SHanna Reitz 3329ffd6d64SHanna Reitz $QSD \ 3339ffd6d64SHanna Reitz --blockdev file,node-name=export-node,filename="$TEST_IMG" \ 334348a0740SHanna Reitz --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=off,allow-other=off \ 3359ffd6d64SHanna Reitz --pidfile "$TEST_DIR/qsd.pid" \ 3369ffd6d64SHanna Reitz --daemonize 3379ffd6d64SHanna Reitzfi 3389ffd6d64SHanna Reitz 3399ffd6d64SHanna Reitz# Now create a qcow2 image on the device -- unfortunately, qemu-img 3409ffd6d64SHanna Reitz# create force-creates the file, so we have to resort to the 3419ffd6d64SHanna Reitz# blockdev-create job. 3429ffd6d64SHanna Reitz_launch_qemu \ 3439ffd6d64SHanna Reitz --blockdev $export_mp_driver,node-name=file,filename="$export_mp" 3449ffd6d64SHanna Reitz 3459ffd6d64SHanna Reitz_send_qemu_cmd \ 3469ffd6d64SHanna Reitz $QEMU_HANDLE \ 3479ffd6d64SHanna Reitz '{ "execute": "qmp_capabilities" }' \ 3489ffd6d64SHanna Reitz 'return' 3499ffd6d64SHanna Reitz 3509ffd6d64SHanna Reitz# Small cluster size again, so the image needs multiple refblocks 3519ffd6d64SHanna Reitz_send_qemu_cmd \ 3529ffd6d64SHanna Reitz $QEMU_HANDLE \ 3539ffd6d64SHanna Reitz '{ "execute": "blockdev-create", 3549ffd6d64SHanna Reitz "arguments": { 3559ffd6d64SHanna Reitz "job-id": "create", 3569ffd6d64SHanna Reitz "options": { 3579ffd6d64SHanna Reitz "driver": "qcow2", 3589ffd6d64SHanna Reitz "file": "file", 3599ffd6d64SHanna Reitz "size": '$((64 * 1024 * 1024))', 3609ffd6d64SHanna Reitz "cluster-size": 512 3619ffd6d64SHanna Reitz } } }' \ 3629ffd6d64SHanna Reitz '"concluded"' 3639ffd6d64SHanna Reitz 3649ffd6d64SHanna Reitz_send_qemu_cmd \ 3659ffd6d64SHanna Reitz $QEMU_HANDLE \ 3669ffd6d64SHanna Reitz '{ "execute": "job-dismiss", "arguments": { "id": "create" } }' \ 3679ffd6d64SHanna Reitz 'return' 3689ffd6d64SHanna Reitz 3699ffd6d64SHanna Reitz_send_qemu_cmd \ 3709ffd6d64SHanna Reitz $QEMU_HANDLE \ 3719ffd6d64SHanna Reitz '{ "execute": "quit" }' \ 3729ffd6d64SHanna Reitz 'return' 3739ffd6d64SHanna Reitz 3749ffd6d64SHanna Reitzwait=y _cleanup_qemu 3759ffd6d64SHanna Reitzecho 3769ffd6d64SHanna Reitz 3779ffd6d64SHanna Reitz# Write some data 3789ffd6d64SHanna Reitz$QEMU_IO -c 'write 0 64k' "$export_mp" | _filter_qemu_io 3799ffd6d64SHanna Reitz 3809ffd6d64SHanna Reitz# Corrupt the image by saying the image header was not allocated 3819ffd6d64SHanna Reitzrt_offset=$(peek_file_be "$export_mp" 48 8) 3829ffd6d64SHanna Reitzrb_offset=$(peek_file_be "$export_mp" $rt_offset 8) 3839ffd6d64SHanna Reitzpoke_file "$export_mp" $rb_offset "\x00\x00" 3849ffd6d64SHanna Reitz 3859ffd6d64SHanna Reitz# Repairing such a simple case should just work 3869ffd6d64SHanna Reitz# (We used to put the reftable at the end of the image file, which can 3879ffd6d64SHanna Reitz# never work for non-growable devices.) 3889ffd6d64SHanna Reitzecho 3899ffd6d64SHanna ReitzTEST_IMG="$export_mp" _check_test_img -r all \ 3909ffd6d64SHanna Reitz | grep -v '^Repairing cluster.*refcount=1 reference=0' 3919ffd6d64SHanna Reitz 3929ffd6d64SHanna Reitzif $loopdev; then 3939ffd6d64SHanna Reitz sudo -n losetup -d "$export_mp" 3949ffd6d64SHanna Reitzelse 3959ffd6d64SHanna Reitz qsd_pid=$(cat "$TEST_DIR/qsd.pid") 3969ffd6d64SHanna Reitz kill -TERM "$qsd_pid" 3979ffd6d64SHanna Reitz # Wait for process to exit (cannot `wait` because the QSD is daemonized) 3989ffd6d64SHanna Reitz while [ -f "$TEST_DIR/qsd.pid" ]; do 3999ffd6d64SHanna Reitz true 4009ffd6d64SHanna Reitz done 4019ffd6d64SHanna Reitzfi 4029ffd6d64SHanna Reitz 403234764eeSMax Reitz# success, all done 404234764eeSMax Reitzecho '*** done' 405234764eeSMax Reitzrm -f $seq.full 406234764eeSMax Reitzstatus=0 407