xref: /qemu/tests/qemu-iotests/251 (revision 42a5009d)
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