1#!/usr/bin/env bash 2# 3# Test some qemu-img convert cases 4# 5# Copyright (C) 2015 Red Hat, Inc. 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20 21# creator 22owner=kwolf@redhat.com 23 24seq="$(basename $0)" 25echo "QA output created by $seq" 26 27status=1 # failure is the default! 28 29_cleanup() 30{ 31 for img in "$TEST_IMG".[123]; do 32 _rm_test_img "$img" 33 done 34 _cleanup_test_img 35} 36trap "_cleanup; exit \$status" 0 1 2 3 15 37 38# get standard environment, filters and checks 39. ./common.rc 40. ./common.filter 41 42_supported_fmt qcow2 43_supported_proto file 44_supported_os Linux 45 46 47TEST_IMG="$TEST_IMG".base _make_test_img 64M 48$QEMU_IO -c "write -P 0x11 0 64M" "$TEST_IMG".base 2>&1 | _filter_qemu_io | _filter_testdir 49 50 51echo 52echo "=== Check allocation status regression with -B ===" 53echo 54 55_make_test_img -b "$TEST_IMG".base -F $IMGFMT 56$QEMU_IO -c "write -P 0x22 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 57$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base \ 58 -o backing_fmt=$IMGFMT "$TEST_IMG" "$TEST_IMG".orig 59$QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map 60 61 62echo 63echo "=== Check that zero clusters are kept in overlay ===" 64echo 65 66_make_test_img -b "$TEST_IMG".base -F $IMGFMT 67 68$QEMU_IO -c "write -P 0 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 69$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ 70 "$TEST_IMG" "$TEST_IMG".orig 71$QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 72$QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ 73 "$TEST_IMG" "$TEST_IMG".orig 74$QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 75 76$QEMU_IO -c "write -z 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 77$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ 78 "$TEST_IMG" "$TEST_IMG".orig 79$QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 80$QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base -o backing_fmt=$IMGFMT \ 81 "$TEST_IMG" "$TEST_IMG".orig 82$QEMU_IO -c "read -P 0 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 83 84 85echo 86echo "=== Converting to an overlay larger than its backing file ===" 87echo 88 89TEST_IMG="$TEST_IMG".base _make_test_img 256M 90# Needs to be at least how much an L2 table covers 91# (64 kB/entry * 64 kB / 8 B/entry = 512 MB) 92# That way, qcow2 will yield at least two status request responses. 93# With just a single response, it would always say "Allocated in the 94# backing file", so the optimization qemu-img convert tries to do is 95# done automatically. Once it has to be queried twice, however (and 96# one of the queries is completely after the end of the backing file), 97# the block layer will automatically add a ZERO flag that qemu-img 98# convert used to follow up with a zero write to the target. 99# We do not want such a zero write, however, because we are past the 100# end of the backing file on the target as well, so we do not need to 101# write anything there. 102_make_test_img -b "$TEST_IMG".base 768M -F $IMGFMT 103 104# Use compat=0.10 as the output so there is no zero cluster support 105$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o compat=0.10 \ 106 -o backing_fmt=$IMGFMT "$TEST_IMG" "$TEST_IMG".orig 107# See that nothing has been allocated past 64M 108$QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map 109 110echo 111 112# Just before the end of the backing file 113$QEMU_IO -c 'write -P 0x11 255M 1M' "$TEST_IMG".base 2>&1 | _filter_qemu_io 114# Somewhere in the second L2 table 115$QEMU_IO -c 'write -P 0x22 600M 1M' "$TEST_IMG" 2>&1 | _filter_qemu_io 116 117$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -o compat=0.10 \ 118 -o backing_fmt=$IMGFMT "$TEST_IMG" "$TEST_IMG".orig 119 120$QEMU_IMG map "$TEST_IMG".orig | _filter_qemu_img_map 121$QEMU_IO -c 'read -P 0x11 255M 1M' \ 122 -c 'read -P 0x22 600M 1M' \ 123 "$TEST_IMG".orig \ 124 | _filter_qemu_io 125 126 127echo 128echo "=== Concatenate multiple source images ===" 129echo 130 131TEST_IMG="$TEST_IMG".1 _make_test_img 4M 132TEST_IMG="$TEST_IMG".2 _make_test_img 4M 133TEST_IMG="$TEST_IMG".3 _make_test_img 4M 134 135$QEMU_IO -c "write -P 0x11 0 64k" "$TEST_IMG".1 2>&1 | _filter_qemu_io | _filter_testdir 136$QEMU_IO -c "write -P 0x22 0 64k" "$TEST_IMG".2 2>&1 | _filter_qemu_io | _filter_testdir 137$QEMU_IO -c "write -P 0x33 0 64k" "$TEST_IMG".3 2>&1 | _filter_qemu_io | _filter_testdir 138 139$QEMU_IMG convert -O $IMGFMT "$TEST_IMG".[123] "$TEST_IMG" 140$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map 141$QEMU_IO -c "read -P 0x11 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 142$QEMU_IO -c "read -P 0x22 4M 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 143$QEMU_IO -c "read -P 0x33 8M 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 144 145$QEMU_IMG convert -c -O $IMGFMT "$TEST_IMG".[123] "$TEST_IMG" 146$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map 147$QEMU_IO -c "read -P 0x11 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 148$QEMU_IO -c "read -P 0x22 4M 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 149$QEMU_IO -c "read -P 0x33 8M 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 150 151# -B can't be combined with concatenation 152$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base "$TEST_IMG".[123] "$TEST_IMG" 153$QEMU_IMG convert -O $IMGFMT -c -B "$TEST_IMG".base "$TEST_IMG".[123] "$TEST_IMG" 154 155 156echo 157echo "=== Compression with misaligned allocations and image sizes ===" 158echo 159 160TEST_IMG="$TEST_IMG".1 _make_test_img 1023k -o cluster_size=1024 161TEST_IMG="$TEST_IMG".2 _make_test_img 1023k -o cluster_size=1024 162 163$QEMU_IO -c "write -P 0x11 16k 16k" "$TEST_IMG".1 2>&1 | _filter_qemu_io | _filter_testdir 164$QEMU_IO -c "write -P 0x22 130k 130k" "$TEST_IMG".1 2>&1 | _filter_qemu_io | _filter_testdir 165$QEMU_IO -c "write -P 0x33 1022k 1k" "$TEST_IMG".1 2>&1 | _filter_qemu_io | _filter_testdir 166$QEMU_IO -c "write -P 0x44 0k 1k" "$TEST_IMG".2 2>&1 | _filter_qemu_io | _filter_testdir 167 168$QEMU_IMG convert -c -O $IMGFMT "$TEST_IMG".[12] "$TEST_IMG" 169$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map 170$QEMU_IO -c "read -P 0 0k 16k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 171$QEMU_IO -c "read -P 0x11 16k 16k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 172$QEMU_IO -c "read -P 0 32k 98k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 173$QEMU_IO -c "read -P 0x22 130k 130k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 174$QEMU_IO -c "read -P 0 260k 762k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 175$QEMU_IO -c "read -P 0x33 1022k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 176$QEMU_IO -c "read -P 0x44 1023k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 177$QEMU_IO -c "read -P 0 1024k 1022k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 178 179 180echo 181echo "=== Full allocation with -S 0 ===" 182echo 183 184# Standalone image 185_make_test_img 64M 186$QEMU_IO -c "write -P 0x22 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 187$QEMU_IO -c "write -P 0 3M 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 188 189echo 190echo convert -S 0: 191$QEMU_IMG convert -O $IMGFMT -S 0 "$TEST_IMG" "$TEST_IMG".orig 192$QEMU_IO -c "read -P 0x22 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 193$QEMU_IO -c "read -P 0 3M 61M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 194$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 195 196echo 197echo convert -c -S 0: 198$QEMU_IMG convert -O $IMGFMT -c -S 0 "$TEST_IMG" "$TEST_IMG".orig 199$QEMU_IO -c "read -P 0x22 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 200$QEMU_IO -c "read -P 0 3M 61M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 201$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 202 203# With backing file 204TEST_IMG="$TEST_IMG".base _make_test_img 64M 205$QEMU_IO -c "write -P 0x11 0 32M" "$TEST_IMG".base 2>&1 | _filter_qemu_io | _filter_testdir 206 207_make_test_img -b "$TEST_IMG".base 64M -F $IMGFMT 208$QEMU_IO -c "write -P 0x22 0 3M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 209 210echo 211echo convert -S 0 with source backing file: 212$QEMU_IMG convert -O $IMGFMT -S 0 "$TEST_IMG" "$TEST_IMG".orig 213$QEMU_IO -c "read -P 0x22 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 214$QEMU_IO -c "read -P 0x11 3M 29M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 215$QEMU_IO -c "read -P 0 32M 32M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 216$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 217 218echo 219echo convert -c -S 0 with source backing file: 220$QEMU_IMG convert -O $IMGFMT -c -S 0 "$TEST_IMG" "$TEST_IMG".orig 221$QEMU_IO -c "read -P 0x22 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 222$QEMU_IO -c "read -P 0x11 3M 29M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 223$QEMU_IO -c "read -P 0 32M 32M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 224$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 225 226# With keeping the backing file 227echo 228echo convert -S 0 -B ... 229$QEMU_IMG convert -O $IMGFMT -S 0 "$TEST_IMG" "$TEST_IMG".orig 230$QEMU_IO -c "read -P 0x22 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 231$QEMU_IO -c "read -P 0x11 3M 29M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 232$QEMU_IO -c "read -P 0 32M 32M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 233$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 234 235echo 236echo convert -c -S 0 -B ... 237$QEMU_IMG convert -O $IMGFMT -c -S 0 "$TEST_IMG" "$TEST_IMG".orig 238$QEMU_IO -c "read -P 0x22 0 3M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 239$QEMU_IO -c "read -P 0x11 3M 29M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 240$QEMU_IO -c "read -P 0 32M 32M" "$TEST_IMG".orig 2>&1 | _filter_qemu_io | _filter_testdir 241$QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 242 243 244echo 245echo "=== Non-zero -S ===" 246echo 247 248_make_test_img 64M -o cluster_size=1k 249$QEMU_IO -c "write -P 0 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 250$QEMU_IO -c "write 0 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 251$QEMU_IO -c "write 8k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 252$QEMU_IO -c "write 17k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir 253 254for min_sparse in 4k 8k; do 255 echo 256 echo convert -S $min_sparse 257 $QEMU_IMG convert -O $IMGFMT -o cluster_size=1k -S $min_sparse "$TEST_IMG" "$TEST_IMG".orig 258 $QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 259 260 echo 261 echo convert -c -S $min_sparse 262 # For compressed images, -S values other than 0 are ignored 263 $QEMU_IMG convert -O $IMGFMT -o cluster_size=1k -c -S $min_sparse "$TEST_IMG" "$TEST_IMG".orig 264 $QEMU_IMG map --output=json "$TEST_IMG".orig | _filter_qemu_img_map 265done 266 267 268echo 269echo '=== -n to a non-zero image ===' 270echo 271 272# Keep source zero 273_make_test_img 64M 274 275# Output is not zero, but has bdrv_has_zero_init() == 1 276TEST_IMG="$TEST_IMG".orig _make_test_img 64M 277$QEMU_IO -c "write -P 42 0 64k" "$TEST_IMG".orig | _filter_qemu_io 278 279# Convert with -n, which should not assume that the target is zeroed 280$QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG".orig 281 282$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG".orig 283 284echo 285echo '=== -n to an empty image ===' 286echo 287 288TEST_IMG="$TEST_IMG".orig _make_test_img 64M 289 290# Convert with -n, which should not result in a fully allocated image, not even 291# with compat=0.10 (because the target doesn't have a backing file) 292for compat in "1.1" "0.10"; do 293 IMGOPTS="compat=$compat" _make_test_img 64M 294 $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG".orig "$TEST_IMG" 295 $QEMU_IMG map --output=json "$TEST_IMG" 296done 297 298echo 299echo '=== -n to an empty image with a backing file ===' 300echo 301 302TEST_IMG="$TEST_IMG".orig _make_test_img 64M 303TEST_IMG="$TEST_IMG".base _make_test_img 64M 304 305# Convert with -n, which should still not result in a fully allocated image for 306# compat=1.1 (because it can use zero clusters), but it should be fully 307# allocated with compat=0.10 308for compat in "1.1" "0.10"; do 309 IMGOPTS="compat=$compat" _make_test_img -b "$TEST_IMG".base -F $IMGFMT 64M 310 $QEMU_IMG convert -O $IMGFMT -n "$TEST_IMG".orig "$TEST_IMG" 311 $QEMU_IMG map --output=json "$TEST_IMG" 312done 313 314echo 315echo '=== -n -B to an image without a backing file ===' 316echo 317 318# Base for the output 319TEST_IMG="$TEST_IMG".base _make_test_img 64M 320 321# Output that does have $TEST_IMG.base set as its (implicit) backing file 322TEST_IMG="$TEST_IMG".orig _make_test_img 64M 323 324# Convert with -n, which should not confuse -B with "target BDS has a 325# backing file" 326$QEMU_IMG convert -O $IMGFMT -B "$TEST_IMG".base -n "$TEST_IMG" "$TEST_IMG".orig 327 328echo 329echo '=== -n incompatible with -o ===' 330echo 331 332$QEMU_IMG convert -O $IMGFMT -o preallocation=metadata -n \ 333 "$TEST_IMG" "$TEST_IMG".orig && echo "unexpected success" 334 335# success, all done 336echo '*** done' 337rm -f $seq.full 338status=0 339