10b1eb0ceSMax Reitz#!/usr/bin/env bash 29dd003a9SVladimir Sementsov-Ogievskiy# group: rw auto quick 30b1eb0ceSMax Reitz# 40b1eb0ceSMax Reitz# Test qemu-img convert --salvage 50b1eb0ceSMax Reitz# 60b1eb0ceSMax Reitz# Copyright (C) 2019 Red Hat, Inc. 70b1eb0ceSMax Reitz# 80b1eb0ceSMax Reitz# This program is free software; you can redistribute it and/or modify 90b1eb0ceSMax Reitz# it under the terms of the GNU General Public License as published by 100b1eb0ceSMax Reitz# the Free Software Foundation; either version 2 of the License, or 110b1eb0ceSMax Reitz# (at your option) any later version. 120b1eb0ceSMax Reitz# 130b1eb0ceSMax Reitz# This program is distributed in the hope that it will be useful, 140b1eb0ceSMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of 150b1eb0ceSMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 160b1eb0ceSMax Reitz# GNU General Public License for more details. 170b1eb0ceSMax Reitz# 180b1eb0ceSMax Reitz# You should have received a copy of the GNU General Public License 190b1eb0ceSMax Reitz# along with this program. If not, see <http://www.gnu.org/licenses/>. 200b1eb0ceSMax Reitz# 210b1eb0ceSMax Reitz 220b1eb0ceSMax Reitz# creator 23*42a5009dSJohn Snowowner=hreitz@redhat.com 240b1eb0ceSMax Reitz 250b1eb0ceSMax Reitzseq=$(basename $0) 260b1eb0ceSMax Reitzecho "QA output created by $seq" 270b1eb0ceSMax Reitz 280b1eb0ceSMax Reitzstatus=1 # failure is the default! 290b1eb0ceSMax Reitz 300b1eb0ceSMax Reitz_cleanup() 310b1eb0ceSMax Reitz{ 320b1eb0ceSMax Reitz _cleanup_test_img 330b1eb0ceSMax Reitz} 340b1eb0ceSMax Reitztrap "_cleanup; exit \$status" 0 1 2 3 15 350b1eb0ceSMax Reitz 360b1eb0ceSMax Reitz# get standard environment, filters and checks 370b1eb0ceSMax Reitz. ./common.rc 380b1eb0ceSMax Reitz. ./common.filter 390b1eb0ceSMax Reitz. ./common.qemu 400b1eb0ceSMax Reitz 410b1eb0ceSMax Reitz_supported_fmt generic 420b1eb0ceSMax Reitz_supported_proto file 430b1eb0ceSMax Reitz_supported_os Linux 44325dd915SMax Reitz_unsupported_imgopts "subformat=streamOptimized" 450b1eb0ceSMax Reitz 460b1eb0ceSMax Reitzif [ "$IMGOPTSSYNTAX" = "true" ]; then 470b1eb0ceSMax Reitz # We use json:{} filenames here, so we cannot work with additional options. 480b1eb0ceSMax Reitz _unsupported_fmt $IMGFMT 490b1eb0ceSMax Reitzelse 50af8d43d3SPeter Lieven # - With VDI, the output is ordered differently. Just disable it. 51af8d43d3SPeter Lieven # - VHDX has large clusters; because qemu-img convert tries to 52af8d43d3SPeter Lieven # align the requests to the cluster size, the output is ordered 53af8d43d3SPeter Lieven # differently, so disable it, too. 54af8d43d3SPeter Lieven _unsupported_fmt vdi vhdx 550b1eb0ceSMax Reitzfi 560b1eb0ceSMax Reitz 570b1eb0ceSMax Reitz 580b1eb0ceSMax ReitzTEST_IMG="$TEST_IMG.orig" _make_test_img 64M 590b1eb0ceSMax Reitz 600b1eb0ceSMax Reitz$QEMU_IO -c 'write -P 42 0 64M' "$TEST_IMG.orig" | _filter_qemu_io 610b1eb0ceSMax Reitz 620b1eb0ceSMax Reitz 630b1eb0ceSMax Reitzsector_size=512 640b1eb0ceSMax Reitz 650b1eb0ceSMax Reitz# Offsets on which to fail block-status. Keep in ascending order so 660b1eb0ceSMax Reitz# the indexing done by _filter_offsets will appear in ascending order 670b1eb0ceSMax Reitz# in the output as well. 680b1eb0ceSMax Reitzstatus_fail_offsets="$((16 * 1024 * 1024 + 8192)) 690b1eb0ceSMax Reitz $((33 * 1024 * 1024 + 512))" 700b1eb0ceSMax Reitz 710b1eb0ceSMax Reitz# Offsets on which to fail reads. Keep in ascending order for the 720b1eb0ceSMax Reitz# same reason. 730b1eb0ceSMax Reitz# The second element is shared with $status_fail_offsets on purpose. 740b1eb0ceSMax Reitz# Starting with the third element, we test what happens when a 750b1eb0ceSMax Reitz# continuous range of sectors is inaccessible. 760b1eb0ceSMax Reitzread_fail_offsets="$((32 * 1024 * 1024 - 65536)) 770b1eb0ceSMax Reitz $((33 * 1024 * 1024 + 512)) 780b1eb0ceSMax Reitz $(seq $((34 * 1024 * 1024)) $sector_size \ 790b1eb0ceSMax Reitz $((34 * 1024 * 1024 + 4096 - $sector_size)))" 800b1eb0ceSMax Reitz 810b1eb0ceSMax Reitz 820b1eb0ceSMax Reitz# blkdebug must be above the format layer so it can intercept all 830b1eb0ceSMax Reitz# block-status events 840b1eb0ceSMax Reitzsource_img="json:{'driver': 'blkdebug', 850b1eb0ceSMax Reitz 'image': { 860b1eb0ceSMax Reitz 'driver': '$IMGFMT', 870b1eb0ceSMax Reitz 'file': { 880b1eb0ceSMax Reitz 'driver': 'file', 890b1eb0ceSMax Reitz 'filename': '$TEST_IMG.orig' 900b1eb0ceSMax Reitz } 910b1eb0ceSMax Reitz }, 920b1eb0ceSMax Reitz 'inject-error': [" 930b1eb0ceSMax Reitz 940b1eb0ceSMax Reitzfor ofs in $status_fail_offsets 950b1eb0ceSMax Reitzdo 960b1eb0ceSMax Reitz source_img+="{ 'event': 'none', 970b1eb0ceSMax Reitz 'iotype': 'block-status', 980b1eb0ceSMax Reitz 'errno': 5, 990b1eb0ceSMax Reitz 'sector': $((ofs / sector_size)) }," 1000b1eb0ceSMax Reitzdone 1010b1eb0ceSMax Reitz 1020b1eb0ceSMax Reitzfor ofs in $read_fail_offsets 1030b1eb0ceSMax Reitzdo 1040b1eb0ceSMax Reitz source_img+="{ 'event': 'none', 1050b1eb0ceSMax Reitz 'iotype': 'read', 1060b1eb0ceSMax Reitz 'errno': 5, 1070b1eb0ceSMax Reitz 'sector': $((ofs / sector_size)) }," 1080b1eb0ceSMax Reitzdone 1090b1eb0ceSMax Reitz 1100b1eb0ceSMax Reitz# Remove the trailing comma and terminate @inject-error and json:{} 1110b1eb0ceSMax Reitzsource_img="${source_img%,} ] }" 1120b1eb0ceSMax Reitz 1130b1eb0ceSMax Reitz 1140b1eb0ceSMax Reitzecho 1150b1eb0ceSMax Reitz 1160b1eb0ceSMax Reitz 1170b1eb0ceSMax Reitz_filter_offsets() { 1180b1eb0ceSMax Reitz filters= 1190b1eb0ceSMax Reitz 1200b1eb0ceSMax Reitz index=0 1210b1eb0ceSMax Reitz for ofs in $1 1220b1eb0ceSMax Reitz do 1230b1eb0ceSMax Reitz filters+=" -e s/$ofs/status_fail_offset_$index/" 1240b1eb0ceSMax Reitz index=$((index + 1)) 1250b1eb0ceSMax Reitz done 1260b1eb0ceSMax Reitz 1270b1eb0ceSMax Reitz index=0 1280b1eb0ceSMax Reitz for ofs in $2 1290b1eb0ceSMax Reitz do 1300b1eb0ceSMax Reitz filters+=" -e s/$ofs/read_fail_offset_$index/" 1310b1eb0ceSMax Reitz index=$((index + 1)) 1320b1eb0ceSMax Reitz done 1330b1eb0ceSMax Reitz 1340b1eb0ceSMax Reitz sed $filters 1350b1eb0ceSMax Reitz} 1360b1eb0ceSMax Reitz 1370b1eb0ceSMax Reitz# While determining the number of allocated sectors in the input 1380b1eb0ceSMax Reitz# image, we should see one block status warning per element of 1390b1eb0ceSMax Reitz# $status_fail_offsets. 1400b1eb0ceSMax Reitz# 1410b1eb0ceSMax Reitz# Then, the image is read. Since the block status is queried in 1420b1eb0ceSMax Reitz# basically the same way, the same warnings as in the previous step 1430b1eb0ceSMax Reitz# should reappear. Interleaved with those we should see a read 1440b1eb0ceSMax Reitz# warning per element of $read_fail_offsets. 1450b1eb0ceSMax Reitz# Note that $read_fail_offsets and $status_fail_offsets share an 1460b1eb0ceSMax Reitz# element (read_fail_offset_1 == status_fail_offset_1), so 1470b1eb0ceSMax Reitz# "status_fail_offset_1" in the output is the same as 1480b1eb0ceSMax Reitz# "read_fail_offset_1". 1490b1eb0ceSMax Reitz$QEMU_IMG convert --salvage "$source_img" "$TEST_IMG" 2>&1 \ 1500b1eb0ceSMax Reitz | _filter_offsets "$status_fail_offsets" "$read_fail_offsets" 1510b1eb0ceSMax Reitz 1520b1eb0ceSMax Reitzecho 1530b1eb0ceSMax Reitz 1540b1eb0ceSMax Reitz# The offsets where the block status could not be determined should 1550b1eb0ceSMax Reitz# have been treated as containing data and thus should be correct in 1560b1eb0ceSMax Reitz# the output image. 1570b1eb0ceSMax Reitz# The offsets where reading failed altogether should be 0. Make them 1580b1eb0ceSMax Reitz# 0 in the input image, too, so we can compare both images. 1590b1eb0ceSMax Reitzfor ofs in $read_fail_offsets 1600b1eb0ceSMax Reitzdo 1610b1eb0ceSMax Reitz $QEMU_IO -c "write -z $ofs $sector_size" "$TEST_IMG.orig" \ 1620b1eb0ceSMax Reitz | _filter_qemu_io \ 1630b1eb0ceSMax Reitz | _filter_offsets '' "$read_fail_offsets" 1640b1eb0ceSMax Reitzdone 1650b1eb0ceSMax Reitz 1660b1eb0ceSMax Reitzecho 1670b1eb0ceSMax Reitz 1680b1eb0ceSMax Reitz# These should be equal now. 1690b1eb0ceSMax Reitz$QEMU_IMG compare "$TEST_IMG.orig" "$TEST_IMG" 1700b1eb0ceSMax Reitz 1710b1eb0ceSMax Reitz 1720b1eb0ceSMax Reitz# success, all done 1730b1eb0ceSMax Reitzecho "*** done" 1740b1eb0ceSMax Reitzrm -f $seq.full 1750b1eb0ceSMax Reitzstatus=0 176