57284d2ada
Many tests (that do not support generic protocols) can run just fine with FUSE-exported images, so allow them to. Note that this is no attempt at being definitely complete. There are some tests that might be modified to run on FUSE, but this patch still skips them. This patch only tries to pick the rather low-hanging fruits. Note that 221 and 250 only pass when .lseek is correctly implemented, which is only possible with a libfuse that is 3.8 or newer. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-Id: <20201027190600.192171-20-mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
140 lines
5.2 KiB
Bash
Executable File
140 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Test qcow2 image compression
|
|
#
|
|
# Copyright (C) 2018 Igalia, S.L.
|
|
# Author: Alberto Garcia <berto@igalia.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
seq=$(basename "$0")
|
|
echo "QA output created by $seq"
|
|
|
|
status=1 # failure is the default!
|
|
|
|
_cleanup()
|
|
{
|
|
_cleanup_test_img
|
|
}
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
|
# get standard environment, filters and checks
|
|
. ./common.rc
|
|
. ./common.filter
|
|
|
|
_supported_fmt qcow2
|
|
_supported_proto file fuse
|
|
|
|
# Repairing the corrupted image requires qemu-img check to store a
|
|
# refcount up to 3, which requires at least two refcount bits.
|
|
# External data files do not support compressed clusters.
|
|
_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
|
|
|
|
|
|
echo
|
|
echo "=== Corrupted size field in compressed cluster descriptor ==="
|
|
echo
|
|
# Create an empty image and fill half of it with compressed data.
|
|
# The L2 entries of the two compressed clusters are located at
|
|
# 0x800000 and 0x800008, their original values are 0x4008000000a00000
|
|
# and 0x4008000000a00802 (5 sectors for compressed data each).
|
|
_make_test_img 8M -o cluster_size=2M
|
|
$QEMU_IO -c "write -c -P 0x11 0 2M" -c "write -c -P 0x11 2M 2M" "$TEST_IMG" \
|
|
2>&1 | _filter_qemu_io | _filter_testdir
|
|
|
|
# Reduce size of compressed data to 4 sectors: this corrupts the image.
|
|
poke_file "$TEST_IMG" $((0x800000)) "\x40\x06"
|
|
$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
|
|
|
|
# 'qemu-img check' however doesn't see anything wrong because it
|
|
# doesn't try to decompress the data and the refcounts are consistent.
|
|
# TODO: update qemu-img so this can be detected.
|
|
_check_test_img
|
|
|
|
# Increase size of compressed data to the maximum (8192 sectors).
|
|
# This makes QEMU read more data (8192 sectors instead of 5, host
|
|
# addresses [0xa00000, 0xdfffff]), but the decompression algorithm
|
|
# stops once we have enough to restore the uncompressed cluster, so
|
|
# the rest of the data is ignored.
|
|
poke_file "$TEST_IMG" $((0x800000)) "\x7f\xfe"
|
|
# Do it also for the second compressed cluster (L2 entry at 0x800008).
|
|
# In this case the compressed data would span 3 host clusters
|
|
# (host addresses: [0xa00802, 0xe00801])
|
|
poke_file "$TEST_IMG" $((0x800008)) "\x7f\xfe"
|
|
|
|
# Here the image is too small so we're asking QEMU to read beyond the
|
|
# end of the image.
|
|
$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
|
|
# But if we grow the image we won't be reading beyond its end anymore.
|
|
$QEMU_IO -c "write -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
|
|
$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
|
|
|
|
# The refcount data is however wrong because due to the increased size
|
|
# of the compressed data it now reaches the following host clusters.
|
|
# This can be repaired by qemu-img check by increasing the refcount of
|
|
# those clusters.
|
|
# TODO: update qemu-img to correct the compressed cluster size instead.
|
|
_check_test_img -r all
|
|
$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
|
|
$QEMU_IO -c "read -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
|
|
|
|
echo
|
|
echo "=== Write compressed data of multiple clusters ==="
|
|
echo
|
|
cluster_size=0x10000
|
|
_make_test_img 2M -o cluster_size=$cluster_size
|
|
|
|
echo "Write uncompressed data:"
|
|
let data_size="8 * $cluster_size"
|
|
$QEMU_IO -c "write -P 0xaa 0 $data_size" "$TEST_IMG" \
|
|
2>&1 | _filter_qemu_io | _filter_testdir
|
|
sizeA=$($QEMU_IMG info --output=json "$TEST_IMG" |
|
|
sed -n '/"actual-size":/ s/[^0-9]//gp')
|
|
|
|
_make_test_img 2M -o cluster_size=$cluster_size
|
|
echo "Write compressed data:"
|
|
let data_size="3 * $cluster_size + $cluster_size / 2"
|
|
# Set compress on. That will align the written data
|
|
# by the cluster size and will write them compressed.
|
|
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
|
|
$QEMU_IO -c "write -P 0xbb 0 $data_size" --image-opts \
|
|
"driver=compress,file.driver=$IMGFMT,file.file.driver=file,file.file.filename=$TEST_IMG" \
|
|
2>&1 | _filter_qemu_io | _filter_testdir
|
|
|
|
let offset="4 * $cluster_size + $cluster_size / 4"
|
|
QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \
|
|
$QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
|
|
'driver': 'compress',
|
|
'file': {'driver': '$IMGFMT',
|
|
'file': {'driver': 'file',
|
|
'filename': '$TEST_IMG'}}}" | \
|
|
_filter_qemu_io | _filter_testdir
|
|
|
|
sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
|
|
sed -n '/"actual-size":/ s/[^0-9]//gp')
|
|
|
|
if [ $sizeA -lt $sizeB ]
|
|
then
|
|
echo "Compression ERROR ($sizeA < $sizeB)"
|
|
fi
|
|
|
|
$QEMU_IMG check --output=json "$TEST_IMG" |
|
|
sed -n 's/,$//; /"compressed-clusters":/ s/^ *//p'
|
|
|
|
# success, all done
|
|
echo '*** done'
|
|
rm -f $seq.full
|
|
status=0
|