xref: /qemu/tests/qemu-iotests/214 (revision 3be2024aefe0024ada2fb5044c230c867ef59c67)
111a82d14SPhilippe Mathieu-Daudé#!/usr/bin/env bash
26cba5377SMax Reitz#
36cba5377SMax Reitz# Test qcow2 image compression
46cba5377SMax Reitz#
56cba5377SMax Reitz# Copyright (C) 2018 Igalia, S.L.
66cba5377SMax Reitz# Author: Alberto Garcia <berto@igalia.com>
76cba5377SMax Reitz#
86cba5377SMax Reitz# This program is free software; you can redistribute it and/or modify
96cba5377SMax Reitz# it under the terms of the GNU General Public License as published by
106cba5377SMax Reitz# the Free Software Foundation; either version 2 of the License, or
116cba5377SMax Reitz# (at your option) any later version.
126cba5377SMax Reitz#
136cba5377SMax Reitz# This program is distributed in the hope that it will be useful,
146cba5377SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of
156cba5377SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
166cba5377SMax Reitz# GNU General Public License for more details.
176cba5377SMax Reitz#
186cba5377SMax Reitz# You should have received a copy of the GNU General Public License
196cba5377SMax Reitz# along with this program.  If not, see <http://www.gnu.org/licenses/>.
206cba5377SMax Reitz#
216cba5377SMax Reitz
226cba5377SMax Reitzseq=$(basename "$0")
236cba5377SMax Reitzecho "QA output created by $seq"
246cba5377SMax Reitz
256cba5377SMax Reitzstatus=1	# failure is the default!
266cba5377SMax Reitz
276cba5377SMax Reitz_cleanup()
286cba5377SMax Reitz{
296cba5377SMax Reitz    _cleanup_test_img
306cba5377SMax Reitz}
316cba5377SMax Reitztrap "_cleanup; exit \$status" 0 1 2 3 15
326cba5377SMax Reitz
336cba5377SMax Reitz# get standard environment, filters and checks
346cba5377SMax Reitz. ./common.rc
356cba5377SMax Reitz. ./common.filter
366cba5377SMax Reitz
376cba5377SMax Reitz_supported_fmt qcow2
386cba5377SMax Reitz_supported_proto file
396cba5377SMax Reitz
406cba5377SMax Reitz# Repairing the corrupted image requires qemu-img check to store a
416cba5377SMax Reitz# refcount up to 3, which requires at least two refcount bits.
42*3be2024aSMax Reitz# External data files do not support compressed clusters.
43*3be2024aSMax Reitz_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file
446cba5377SMax Reitz
456cba5377SMax Reitz
466cba5377SMax Reitzecho
476cba5377SMax Reitzecho "=== Corrupted size field in compressed cluster descriptor ==="
486cba5377SMax Reitzecho
496cba5377SMax Reitz# Create an empty image and fill half of it with compressed data.
506cba5377SMax Reitz# The L2 entries of the two compressed clusters are located at
516cba5377SMax Reitz# 0x800000 and 0x800008, their original values are 0x4008000000a00000
526cba5377SMax Reitz# and 0x4008000000a00802 (5 sectors for compressed data each).
536cba5377SMax Reitz_make_test_img 8M -o cluster_size=2M
546cba5377SMax Reitz$QEMU_IO -c "write -c -P 0x11 0 2M" -c "write -c -P 0x11 2M 2M" "$TEST_IMG" \
556cba5377SMax Reitz         2>&1 | _filter_qemu_io | _filter_testdir
566cba5377SMax Reitz
576cba5377SMax Reitz# Reduce size of compressed data to 4 sectors: this corrupts the image.
586cba5377SMax Reitzpoke_file "$TEST_IMG" $((0x800000)) "\x40\x06"
596cba5377SMax Reitz$QEMU_IO -c "read  -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
606cba5377SMax Reitz
616cba5377SMax Reitz# 'qemu-img check' however doesn't see anything wrong because it
626cba5377SMax Reitz# doesn't try to decompress the data and the refcounts are consistent.
636cba5377SMax Reitz# TODO: update qemu-img so this can be detected.
646cba5377SMax Reitz_check_test_img
656cba5377SMax Reitz
666cba5377SMax Reitz# Increase size of compressed data to the maximum (8192 sectors).
676cba5377SMax Reitz# This makes QEMU read more data (8192 sectors instead of 5, host
686cba5377SMax Reitz# addresses [0xa00000, 0xdfffff]), but the decompression algorithm
696cba5377SMax Reitz# stops once we have enough to restore the uncompressed cluster, so
706cba5377SMax Reitz# the rest of the data is ignored.
716cba5377SMax Reitzpoke_file "$TEST_IMG" $((0x800000)) "\x7f\xfe"
726cba5377SMax Reitz# Do it also for the second compressed cluster (L2 entry at 0x800008).
736cba5377SMax Reitz# In this case the compressed data would span 3 host clusters
746cba5377SMax Reitz# (host addresses: [0xa00802, 0xe00801])
756cba5377SMax Reitzpoke_file "$TEST_IMG" $((0x800008)) "\x7f\xfe"
766cba5377SMax Reitz
776cba5377SMax Reitz# Here the image is too small so we're asking QEMU to read beyond the
786cba5377SMax Reitz# end of the image.
796cba5377SMax Reitz$QEMU_IO -c "read  -P 0x11  0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
806cba5377SMax Reitz# But if we grow the image we won't be reading beyond its end anymore.
816cba5377SMax Reitz$QEMU_IO -c "write -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
826cba5377SMax Reitz$QEMU_IO -c "read  -P 0x11  0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
836cba5377SMax Reitz
846cba5377SMax Reitz# The refcount data is however wrong because due to the increased size
856cba5377SMax Reitz# of the compressed data it now reaches the following host clusters.
866cba5377SMax Reitz# This can be repaired by qemu-img check by increasing the refcount of
876cba5377SMax Reitz# those clusters.
886cba5377SMax Reitz# TODO: update qemu-img to correct the compressed cluster size instead.
896cba5377SMax Reitz_check_test_img -r all
906cba5377SMax Reitz$QEMU_IO -c "read  -P 0x11  0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
916cba5377SMax Reitz$QEMU_IO -c "read  -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
926cba5377SMax Reitz
936cba5377SMax Reitz# success, all done
946cba5377SMax Reitzecho '*** done'
956cba5377SMax Reitzrm -f $seq.full
966cba5377SMax Reitzstatus=0
97