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