1#!/usr/bin/env bash 2# 3# Test qcow2 images with extended L2 entries 4# 5# Copyright (C) 2019-2020 Igalia, S.L. 6# Author: Alberto Garcia <berto@igalia.com> 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 2 of the License, or 11# (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program. If not, see <http://www.gnu.org/licenses/>. 20# 21 22# creator 23owner=berto@igalia.com 24 25seq="$(basename $0)" 26echo "QA output created by $seq" 27 28here="$PWD" 29status=1 # failure is the default! 30 31_cleanup() 32{ 33 _cleanup_test_img 34 rm -f "$TEST_IMG.raw" 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 nfs 44_supported_os Linux 45_unsupported_imgopts extended_l2 compat=0.10 cluster_size data_file refcount_bits=1[^0-9] 46 47l2_offset=$((0x40000)) 48 49_verify_img() 50{ 51 $QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.raw" | grep -v 'Images are identical' 52 $QEMU_IMG check "$TEST_IMG" | _filter_qemu_img_check | \ 53 grep -v 'No errors were found on the image' 54} 55 56# Compare the bitmap of an extended L2 entry against an expected value 57_verify_l2_bitmap() 58{ 59 entry_no="$1" # L2 entry number, starting from 0 60 expected_alloc="$alloc" # Space-separated list of allocated subcluster indexes 61 expected_zero="$zero" # Space-separated list of zero subcluster indexes 62 63 offset=$(($l2_offset + $entry_no * 16)) 64 entry=$(peek_file_be "$TEST_IMG" $offset 8) 65 offset=$(($offset + 8)) 66 bitmap=$(peek_file_be "$TEST_IMG" $offset 8) 67 68 expected_bitmap=0 69 for bit in $expected_alloc; do 70 expected_bitmap=$(($expected_bitmap | (1 << $bit))) 71 done 72 for bit in $expected_zero; do 73 expected_bitmap=$(($expected_bitmap | (1 << (32 + $bit)))) 74 done 75 printf -v expected_bitmap "%u" $expected_bitmap # Convert to unsigned 76 77 printf "L2 entry #%d: 0x%016x %016x\n" "$entry_no" "$entry" "$bitmap" 78 if [ "$bitmap" != "$expected_bitmap" ]; then 79 printf "ERROR: expecting bitmap 0x%016x\n" "$expected_bitmap" 80 fi 81} 82 83# This should be called as _run_test c=XXX sc=XXX off=XXX len=XXX cmd=XXX 84# c: cluster number (0 if unset) 85# sc: subcluster number inside cluster @c (0 if unset) 86# off: offset inside subcluster @sc, in kilobytes (0 if unset) 87# len: request length, passed directly to qemu-io (e.g: 256, 4k, 1M, ...) 88# cmd: the command to pass to qemu-io, must be one of 89# write -> write 90# zero -> write -z 91# unmap -> write -z -u 92# compress -> write -c 93# discard -> discard 94_run_test() 95{ 96 unset c sc off len cmd 97 for var in "$@"; do eval "$var"; done 98 case "${cmd:-write}" in 99 zero) 100 cmd="write -q -z";; 101 unmap) 102 cmd="write -q -z -u";; 103 compress) 104 pat=$((${pat:-0} + 1)) 105 cmd="write -q -c -P ${pat}";; 106 write) 107 pat=$((${pat:-0} + 1)) 108 cmd="write -q -P ${pat}";; 109 discard) 110 cmd="discard -q";; 111 *) 112 echo "Unknown option $cmd" 113 exit 1;; 114 esac 115 c="${c:-0}" 116 sc="${sc:-0}" 117 off="${off:-0}" 118 offset="$(($c * 64 + $sc * 2 + $off))" 119 [ "$offset" != 0 ] && offset="${offset}k" 120 cmd="$cmd ${offset} ${len}" 121 raw_cmd=$(echo $cmd | sed s/-c//) # Raw images don't support -c 122 echo $cmd | sed 's/-P [0-9][0-9]\?/-P PATTERN/' 123 $QEMU_IO -c "$cmd" "$TEST_IMG" | _filter_qemu_io 124 $QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io 125 _verify_img 126 _verify_l2_bitmap "$c" 127} 128 129_reset_img() 130{ 131 size="$1" 132 $QEMU_IMG create -f raw "$TEST_IMG.raw" "$size" | _filter_img_create 133 if [ "$use_backing_file" = "yes" ]; then 134 $QEMU_IMG create -f raw "$TEST_IMG.base" "$size" | _filter_img_create 135 $QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.base" | _filter_qemu_io 136 $QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.raw" | _filter_qemu_io 137 _make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" "$size" 138 else 139 _make_test_img -o extended_l2=on "$size" 140 fi 141} 142 143############################################################ 144############################################################ 145############################################################ 146 147# Test that writing to an image with subclusters produces the expected 148# results, in images with and without backing files 149for use_backing_file in yes no; do 150 echo 151 echo "### Standard write tests (backing file: $use_backing_file) ###" 152 echo 153 _reset_img 1M 154 ### Write subcluster #0 (beginning of subcluster) ### 155 alloc="0"; zero="" 156 _run_test sc=0 len=1k 157 158 ### Write subcluster #1 (middle of subcluster) ### 159 alloc="0 1"; zero="" 160 _run_test sc=1 off=1 len=512 161 162 ### Write subcluster #2 (end of subcluster) ### 163 alloc="0 1 2"; zero="" 164 _run_test sc=2 off=1 len=1k 165 166 ### Write subcluster #3 (full subcluster) ### 167 alloc="0 1 2 3"; zero="" 168 _run_test sc=3 len=2k 169 170 ### Write subclusters #4-6 (full subclusters) ### 171 alloc="$(seq 0 6)"; zero="" 172 _run_test sc=4 len=6k 173 174 ### Write subclusters #7-9 (partial subclusters) ### 175 alloc="$(seq 0 9)"; zero="" 176 _run_test sc=7 off=1 len=4k 177 178 ### Write subcluster #16 (partial subcluster) ### 179 alloc="$(seq 0 9) 16"; zero="" 180 _run_test sc=16 len=1k 181 182 ### Write subcluster #31-#33 (cluster overlap) ### 183 alloc="$(seq 0 9) 16 31"; zero="" 184 _run_test sc=31 off=1 len=4k 185 alloc="0 1" ; zero="" 186 _verify_l2_bitmap 1 187 188 ### Zero subcluster #1 189 alloc="0 $(seq 2 9) 16 31"; zero="1" 190 _run_test sc=1 len=2k cmd=zero 191 192 ### Zero cluster #0 193 alloc=""; zero="$(seq 0 31)" 194 _run_test sc=0 len=64k cmd=zero 195 196 ### Fill cluster #0 with data 197 alloc="$(seq 0 31)"; zero="" 198 _run_test sc=0 len=64k 199 200 ### Zero and unmap half of cluster #0 (this won't unmap it) 201 alloc="$(seq 16 31)"; zero="$(seq 0 15)" 202 _run_test sc=0 len=32k cmd=unmap 203 204 ### Zero and unmap cluster #0 205 alloc=""; zero="$(seq 0 31)" 206 _run_test sc=0 len=64k cmd=unmap 207 208 ### Write subcluster #1 (middle of subcluster) 209 alloc="1"; zero="0 $(seq 2 31)" 210 _run_test sc=1 off=1 len=512 211 212 ### Fill cluster #0 with data 213 alloc="$(seq 0 31)"; zero="" 214 _run_test sc=0 len=64k 215 216 ### Discard cluster #0 217 alloc=""; zero="$(seq 0 31)" 218 _run_test sc=0 len=64k cmd=discard 219 220 ### Write compressed data to cluster #0 221 alloc=""; zero="" 222 _run_test sc=0 len=64k cmd=compress 223 224 ### Write subcluster #1 (middle of subcluster) 225 alloc="$(seq 0 31)"; zero="" 226 _run_test sc=1 off=1 len=512 227done 228 229############################################################ 230############################################################ 231############################################################ 232 233# calculate_l2_meta() checks if none of the clusters affected by a 234# write operation need COW or changes to their L2 metadata and simply 235# returns when they don't. This is a test for that optimization. 236# Here clusters #0-#3 are overwritten but only #1 and #2 need changes. 237echo 238echo '### Overwriting several clusters without COW ###' 239echo 240use_backing_file="no" _reset_img 1M 241# Write cluster #0, subclusters #12-#31 242alloc="$(seq 12 31)"; zero="" 243_run_test sc=12 len=40k 244 245# Write cluster #1, subcluster #13 246alloc="13"; zero="" 247_run_test c=1 sc=13 len=2k 248 249# Zeroize cluster #2, subcluster #14 250alloc="14"; zero="" 251_run_test c=2 sc=14 len=2k 252alloc=""; zero="14" 253_run_test c=2 sc=14 len=2k cmd=zero 254 255# Write cluster #3, subclusters #0-#16 256alloc="$(seq 0 16)"; zero="" 257_run_test c=3 sc=0 len=34k 258 259# Write from cluster #0, subcluster #12 to cluster #3, subcluster #11 260alloc="$(seq 12 31)"; zero="" 261_run_test sc=12 len=192k 262alloc="$(seq 0 31)"; zero="" 263_verify_l2_bitmap 1 264_verify_l2_bitmap 2 265 266alloc="$(seq 0 16)"; zero="" 267_verify_l2_bitmap 3 268 269############################################################ 270############################################################ 271############################################################ 272 273# Test different patterns of writing zeroes 274for use_backing_file in yes no; do 275 echo 276 echo "### Writing zeroes 1: unallocated clusters (backing file: $use_backing_file) ###" 277 echo 278 # Note that the image size is not a multiple of the cluster size 279 _reset_img 2083k 280 281 # Cluster-aligned request from clusters #0 to #2 282 alloc=""; zero="$(seq 0 31)" 283 _run_test c=0 sc=0 len=192k cmd=zero 284 _verify_l2_bitmap 1 285 _verify_l2_bitmap 2 286 287 # Subcluster-aligned request from clusters #3 to #5 288 alloc=""; zero="$(seq 16 31)" 289 _run_test c=3 sc=16 len=128k cmd=zero 290 alloc=""; zero="$(seq 0 31)" 291 _verify_l2_bitmap 4 292 alloc=""; zero="$(seq 0 15)" 293 _verify_l2_bitmap 5 294 295 # Unaligned request from clusters #6 to #8 296 if [ "$use_backing_file" = "yes" ]; then 297 alloc="15"; zero="$(seq 16 31)" # copy-on-write happening here 298 else 299 alloc=""; zero="$(seq 15 31)" 300 fi 301 _run_test c=6 sc=15 off=1 len=128k cmd=zero 302 alloc=""; zero="$(seq 0 31)" 303 _verify_l2_bitmap 7 304 if [ "$use_backing_file" = "yes" ]; then 305 alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here 306 else 307 alloc=""; zero="$(seq 0 15)" 308 fi 309 _verify_l2_bitmap 8 310 311 echo 312 echo "### Writing zeroes 2: allocated clusters (backing file: $use_backing_file) ###" 313 echo 314 alloc="$(seq 0 31)"; zero="" 315 _run_test c=9 sc=0 len=576k 316 _verify_l2_bitmap 10 317 _verify_l2_bitmap 11 318 _verify_l2_bitmap 12 319 _verify_l2_bitmap 13 320 _verify_l2_bitmap 14 321 _verify_l2_bitmap 15 322 _verify_l2_bitmap 16 323 _verify_l2_bitmap 17 324 325 # Cluster-aligned request from clusters #9 to #11 326 alloc=""; zero="$(seq 0 31)" 327 _run_test c=9 sc=0 len=192k cmd=zero 328 _verify_l2_bitmap 10 329 _verify_l2_bitmap 11 330 331 # Subcluster-aligned request from clusters #12 to #14 332 alloc="$(seq 0 15)"; zero="$(seq 16 31)" 333 _run_test c=12 sc=16 len=128k cmd=zero 334 alloc=""; zero="$(seq 0 31)" 335 _verify_l2_bitmap 13 336 alloc="$(seq 16 31)"; zero="$(seq 0 15)" 337 _verify_l2_bitmap 14 338 339 # Unaligned request from clusters #15 to #17 340 alloc="$(seq 0 15)"; zero="$(seq 16 31)" 341 _run_test c=15 sc=15 off=1 len=128k cmd=zero 342 alloc=""; zero="$(seq 0 31)" 343 _verify_l2_bitmap 16 344 alloc="$(seq 15 31)"; zero="$(seq 0 14)" 345 _verify_l2_bitmap 17 346 347 echo 348 echo "### Writing zeroes 3: compressed clusters (backing file: $use_backing_file) ###" 349 echo 350 alloc=""; zero="" 351 for c in $(seq 18 28); do 352 _run_test c=$c sc=0 len=64k cmd=compress 353 done 354 355 # Cluster-aligned request from clusters #18 to #20 356 alloc=""; zero="$(seq 0 31)" 357 _run_test c=18 sc=0 len=192k cmd=zero 358 _verify_l2_bitmap 19 359 _verify_l2_bitmap 20 360 361 # Subcluster-aligned request from clusters #21 to #23. 362 # We cannot partially zero a compressed cluster so the code 363 # returns -ENOTSUP, which means copy-on-write of the compressed 364 # data and fill the rest with actual zeroes on disk. 365 # TODO: cluster #22 should use the 'all zeroes' bits. 366 alloc="$(seq 0 31)"; zero="" 367 _run_test c=21 sc=16 len=128k cmd=zero 368 _verify_l2_bitmap 22 369 _verify_l2_bitmap 23 370 371 # Unaligned request from clusters #24 to #26 372 # In this case QEMU internally sends a 1k request followed by a 373 # subcluster-aligned 128k request. The first request decompresses 374 # cluster #24, but that's not enough to perform the second request 375 # efficiently because it partially writes to cluster #26 (which is 376 # compressed) so we hit the same problem as before. 377 alloc="$(seq 0 31)"; zero="" 378 _run_test c=24 sc=15 off=1 len=129k cmd=zero 379 _verify_l2_bitmap 25 380 _verify_l2_bitmap 26 381 382 # Unaligned request from clusters #27 to #29 383 # Similar to the previous case, but this time the tail of the 384 # request does not correspond to a compressed cluster, so it can 385 # be zeroed efficiently. 386 # Note that the very last subcluster is partially written, so if 387 # there's a backing file we need to perform cow. 388 alloc="$(seq 0 15)"; zero="$(seq 16 31)" 389 _run_test c=27 sc=15 off=1 len=128k cmd=zero 390 alloc=""; zero="$(seq 0 31)" 391 _verify_l2_bitmap 28 392 if [ "$use_backing_file" = "yes" ]; then 393 alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here 394 else 395 alloc=""; zero="$(seq 0 15)" 396 fi 397 _verify_l2_bitmap 29 398 399 echo 400 echo "### Writing zeroes 4: other tests (backing file: $use_backing_file) ###" 401 echo 402 # Unaligned request in the middle of cluster #30. 403 # If there's a backing file we need to allocate and do 404 # copy-on-write on the partially zeroed subclusters. 405 # If not we can set the 'all zeroes' bit on them. 406 if [ "$use_backing_file" = "yes" ]; then 407 alloc="15 19"; zero="$(seq 16 18)" # copy-on-write happening here 408 else 409 alloc=""; zero="$(seq 15 19)" 410 fi 411 _run_test c=30 sc=15 off=1 len=8k cmd=zero 412 413 # Fill the last cluster with zeroes, up to the end of the image 414 # (the image size is not a multiple of the cluster or subcluster size). 415 alloc=""; zero="$(seq 0 17)" 416 _run_test c=32 sc=0 len=35k cmd=zero 417done 418 419############################################################ 420############################################################ 421############################################################ 422 423# Zero + unmap 424for use_backing_file in yes no; do 425 echo 426 echo "### Zero + unmap 1: allocated clusters (backing file: $use_backing_file) ###" 427 echo 428 # Note that the image size is not a multiple of the cluster size 429 _reset_img 2083k 430 alloc="$(seq 0 31)"; zero="" 431 _run_test c=9 sc=0 len=576k 432 _verify_l2_bitmap 10 433 _verify_l2_bitmap 11 434 _verify_l2_bitmap 12 435 _verify_l2_bitmap 13 436 _verify_l2_bitmap 14 437 _verify_l2_bitmap 15 438 _verify_l2_bitmap 16 439 _verify_l2_bitmap 17 440 441 # Cluster-aligned request from clusters #9 to #11 442 alloc=""; zero="$(seq 0 31)" 443 _run_test c=9 sc=0 len=192k cmd=unmap 444 _verify_l2_bitmap 10 445 _verify_l2_bitmap 11 446 447 # Subcluster-aligned request from clusters #12 to #14 448 alloc="$(seq 0 15)"; zero="$(seq 16 31)" 449 _run_test c=12 sc=16 len=128k cmd=unmap 450 alloc=""; zero="$(seq 0 31)" 451 _verify_l2_bitmap 13 452 alloc="$(seq 16 31)"; zero="$(seq 0 15)" 453 _verify_l2_bitmap 14 454 455 # Unaligned request from clusters #15 to #17 456 alloc="$(seq 0 15)"; zero="$(seq 16 31)" 457 _run_test c=15 sc=15 off=1 len=128k cmd=unmap 458 alloc=""; zero="$(seq 0 31)" 459 _verify_l2_bitmap 16 460 alloc="$(seq 15 31)"; zero="$(seq 0 14)" 461 _verify_l2_bitmap 17 462 463 echo 464 echo "### Zero + unmap 2: compressed clusters (backing file: $use_backing_file) ###" 465 echo 466 alloc=""; zero="" 467 for c in $(seq 18 28); do 468 _run_test c=$c sc=0 len=64k cmd=compress 469 done 470 471 # Cluster-aligned request from clusters #18 to #20 472 alloc=""; zero="$(seq 0 31)" 473 _run_test c=18 sc=0 len=192k cmd=unmap 474 _verify_l2_bitmap 19 475 _verify_l2_bitmap 20 476 477 # Subcluster-aligned request from clusters #21 to #23. 478 # We cannot partially zero a compressed cluster so the code 479 # returns -ENOTSUP, which means copy-on-write of the compressed 480 # data and fill the rest with actual zeroes on disk. 481 # TODO: cluster #22 should use the 'all zeroes' bits. 482 alloc="$(seq 0 31)"; zero="" 483 _run_test c=21 sc=16 len=128k cmd=unmap 484 _verify_l2_bitmap 22 485 _verify_l2_bitmap 23 486 487 # Unaligned request from clusters #24 to #26 488 # In this case QEMU internally sends a 1k request followed by a 489 # subcluster-aligned 128k request. The first request decompresses 490 # cluster #24, but that's not enough to perform the second request 491 # efficiently because it partially writes to cluster #26 (which is 492 # compressed) so we hit the same problem as before. 493 alloc="$(seq 0 31)"; zero="" 494 _run_test c=24 sc=15 off=1 len=129k cmd=unmap 495 _verify_l2_bitmap 25 496 _verify_l2_bitmap 26 497 498 # Unaligned request from clusters #27 to #29 499 # Similar to the previous case, but this time the tail of the 500 # request does not correspond to a compressed cluster, so it can 501 # be zeroed efficiently. 502 # Note that the very last subcluster is partially written, so if 503 # there's a backing file we need to perform cow. 504 alloc="$(seq 0 15)"; zero="$(seq 16 31)" 505 _run_test c=27 sc=15 off=1 len=128k cmd=unmap 506 alloc=""; zero="$(seq 0 31)" 507 _verify_l2_bitmap 28 508 if [ "$use_backing_file" = "yes" ]; then 509 alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here 510 else 511 alloc=""; zero="$(seq 0 15)" 512 fi 513 _verify_l2_bitmap 29 514done 515 516############################################################ 517############################################################ 518############################################################ 519 520# Test qcow2_cluster_discard() with full and normal discards 521for use_backing_file in yes no; do 522 echo 523 echo "### Discarding clusters with non-zero bitmaps (backing file: $use_backing_file) ###" 524 echo 525 if [ "$use_backing_file" = "yes" ]; then 526 _make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 1M 527 else 528 _make_test_img -o extended_l2=on 1M 529 fi 530 # Write clusters #0-#2 and then discard them 531 $QEMU_IO -c 'write -q 0 128k' "$TEST_IMG" 532 $QEMU_IO -c 'discard -q 0 128k' "$TEST_IMG" 533 # 'qemu-io discard' doesn't do a full discard, it zeroizes the 534 # cluster, so both clusters have all zero bits set now 535 alloc=""; zero="$(seq 0 31)" 536 _verify_l2_bitmap 0 537 _verify_l2_bitmap 1 538 # Now mark the 2nd half of the subclusters from cluster #0 as unallocated 539 poke_file "$TEST_IMG" $(($l2_offset+8)) "\x00\x00" 540 # Discard cluster #0 again to see how the zero bits have changed 541 $QEMU_IO -c 'discard -q 0 64k' "$TEST_IMG" 542 # And do a full discard of cluster #1 by shrinking and growing the image 543 $QEMU_IMG resize --shrink "$TEST_IMG" 64k 544 $QEMU_IMG resize "$TEST_IMG" 1M 545 # A normal discard sets all 'zero' bits only if the image has a 546 # backing file, otherwise it won't touch them. 547 if [ "$use_backing_file" = "yes" ]; then 548 alloc=""; zero="$(seq 0 31)" 549 else 550 alloc=""; zero="$(seq 0 15)" 551 fi 552 _verify_l2_bitmap 0 553 # A full discard should clear the L2 entry completely. However 554 # when growing an image with a backing file the new clusters are 555 # zeroized to hide the stale data from the backing file 556 if [ "$use_backing_file" = "yes" ]; then 557 alloc=""; zero="$(seq 0 31)" 558 else 559 alloc=""; zero="" 560 fi 561 _verify_l2_bitmap 1 562done 563 564############################################################ 565############################################################ 566############################################################ 567 568# Test that corrupted L2 entries are detected in both read and write 569# operations 570for corruption_test_cmd in read write; do 571 echo 572 echo "### Corrupted L2 entries - $corruption_test_cmd test (allocated) ###" 573 echo 574 echo "# 'cluster is zero' bit set on the standard cluster descriptor" 575 echo 576 # We actually don't consider this a corrupted image. 577 # The 'cluster is zero' bit is unused in extended L2 entries so 578 # QEMU ignores it. 579 # TODO: maybe treat the image as corrupted and make qemu-img check fix it? 580 _make_test_img -o extended_l2=on 1M 581 $QEMU_IO -c 'write -q -P 0x11 0 2k' "$TEST_IMG" 582 poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01" 583 alloc="0"; zero="" 584 _verify_l2_bitmap 0 585 $QEMU_IO -c "$corruption_test_cmd -q -P 0x11 0 1k" "$TEST_IMG" 586 if [ "$corruption_test_cmd" = "write" ]; then 587 alloc="0"; zero="" 588 fi 589 _verify_l2_bitmap 0 590 591 echo 592 echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set" 593 echo 594 _make_test_img -o extended_l2=on 1M 595 # Write from the middle of cluster #0 to the middle of cluster #2 596 $QEMU_IO -c 'write -q 32k 128k' "$TEST_IMG" 597 # Corrupt the L2 entry from cluster #1 598 poke_file_be "$TEST_IMG" $(($l2_offset+24)) 4 1 599 alloc="$(seq 0 31)"; zero="0" 600 _verify_l2_bitmap 1 601 $QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG" 602 603 echo 604 echo "### Corrupted L2 entries - $corruption_test_cmd test (unallocated) ###" 605 echo 606 echo "# 'cluster is zero' bit set on the standard cluster descriptor" 607 echo 608 # We actually don't consider this a corrupted image. 609 # The 'cluster is zero' bit is unused in extended L2 entries so 610 # QEMU ignores it. 611 # TODO: maybe treat the image as corrupted and make qemu-img check fix it? 612 _make_test_img -o extended_l2=on 1M 613 # We want to modify the (empty) L2 entry from cluster #0, 614 # but we write to #4 in order to initialize the L2 table first 615 $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG" 616 poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01" 617 alloc=""; zero="" 618 _verify_l2_bitmap 0 619 $QEMU_IO -c "$corruption_test_cmd -q 0 1k" "$TEST_IMG" 620 if [ "$corruption_test_cmd" = "write" ]; then 621 alloc="0"; zero="" 622 fi 623 _verify_l2_bitmap 0 624 625 echo 626 echo "# 'subcluster is allocated' bit set" 627 echo 628 _make_test_img -o extended_l2=on 1M 629 # We want to corrupt the (empty) L2 entry from cluster #0, 630 # but we write to #4 in order to initialize the L2 table first 631 $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG" 632 poke_file "$TEST_IMG" $(($l2_offset+15)) "\x01" 633 alloc="0"; zero="" 634 _verify_l2_bitmap 0 635 $QEMU_IO -c "$corruption_test_cmd 0 1k" "$TEST_IMG" 636 637 echo 638 echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set" 639 echo 640 _make_test_img -o extended_l2=on 1M 641 # We want to corrupt the (empty) L2 entry from cluster #1, 642 # but we write to #4 in order to initialize the L2 table first 643 $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG" 644 # Corrupt the L2 entry from cluster #1 645 poke_file_be "$TEST_IMG" $(($l2_offset+24)) 8 $(((1 << 32) | 1)) 646 alloc="0"; zero="0" 647 _verify_l2_bitmap 1 648 $QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG" 649 650 echo 651 echo "### Compressed cluster with subcluster bitmap != 0 - $corruption_test_cmd test ###" 652 echo 653 # We actually don't consider this a corrupted image. 654 # The bitmap in compressed clusters is unused so QEMU should just ignore it. 655 _make_test_img -o extended_l2=on 1M 656 $QEMU_IO -c 'write -q -P 11 -c 0 64k' "$TEST_IMG" 657 # Change the L2 bitmap to allocate subcluster #31 and zeroize subcluster #0 658 poke_file "$TEST_IMG" $(($l2_offset+11)) "\x01\x80" 659 alloc="31"; zero="0" 660 _verify_l2_bitmap 0 661 $QEMU_IO -c "$corruption_test_cmd -P 11 0 64k" "$TEST_IMG" | _filter_qemu_io 662 # Writing allocates a new uncompressed cluster so we get a new bitmap 663 if [ "$corruption_test_cmd" = "write" ]; then 664 alloc="$(seq 0 31)"; zero="" 665 fi 666 _verify_l2_bitmap 0 667done 668 669############################################################ 670############################################################ 671############################################################ 672 673echo 674echo "### Detect and repair unaligned clusters ###" 675echo 676# Create a backing file and fill it with data 677$QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create 678$QEMU_IO -c "write -q -P 0xff 0 128k" -f raw "$TEST_IMG.base" | _filter_qemu_io 679 680echo "# Corrupted L2 entry, allocated subcluster #" 681# Create a new image, allocate a cluster and write some data to it 682_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 683$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG" 684# Corrupt the L2 entry by making the offset unaligned 685poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02" 686# This cannot be repaired, qemu-img check will fail to fix it 687_check_test_img -r all 688# Attempting to read the image will still show that it's corrupted 689$QEMU_IO -c 'read -q 0 2k' "$TEST_IMG" 690 691echo "# Corrupted L2 entry, no allocated subclusters #" 692# Create a new image, allocate a cluster and zeroize subcluster #2 693_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 694$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG" 695$QEMU_IO -c 'write -q -z 4k 2k' "$TEST_IMG" 696# Corrupt the L2 entry by making the offset unaligned 697poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02" 698# This time none of the subclusters are allocated so we can repair the image 699_check_test_img -r all 700# And the data can be read normally 701$QEMU_IO -c 'read -q -P 0xff 0 4k' "$TEST_IMG" 702$QEMU_IO -c 'read -q -P 0x00 4k 2k' "$TEST_IMG" 703$QEMU_IO -c 'read -q -P 0xff 6k 122k' "$TEST_IMG" 704 705############################################################ 706############################################################ 707############################################################ 708 709echo 710echo "### Image creation options ###" 711echo 712echo "# cluster_size < 16k" 713_make_test_img -o extended_l2=on,cluster_size=8k 1M 714 715echo "# backing file and preallocation=metadata" 716# For preallocation with backing files, create a backing file first 717$QEMU_IMG create -f raw "$TEST_IMG.base" 1M | _filter_img_create 718$QEMU_IO -c "write -q -P 0xff 0 1M" -f raw "$TEST_IMG.base" | _filter_qemu_io 719 720_make_test_img -o extended_l2=on,preallocation=metadata -F raw -b "$TEST_IMG.base" 512k 721$QEMU_IMG resize "$TEST_IMG" 1M 722$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io 723$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io 724$QEMU_IMG map "$TEST_IMG" | _filter_testdir 725 726echo "# backing file and preallocation=falloc" 727_make_test_img -o extended_l2=on,preallocation=falloc -F raw -b "$TEST_IMG.base" 512k 728$QEMU_IMG resize "$TEST_IMG" 1M 729$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io 730$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io 731$QEMU_IMG map "$TEST_IMG" | _filter_testdir 732 733echo "# backing file and preallocation=full" 734_make_test_img -o extended_l2=on,preallocation=full -F raw -b "$TEST_IMG.base" 512k 735$QEMU_IMG resize "$TEST_IMG" 1M 736$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io 737$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io 738$QEMU_IMG map "$TEST_IMG" | _filter_testdir 739 740echo 741echo "### Image resizing with preallocation and backing files ###" 742echo 743# In this case the new subclusters must have the 'all zeroes' bit set 744echo "# resize --preallocation=metadata" 745_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k 746$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k 747$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 748$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io 749 750# In this case and the next one the new subclusters must be allocated 751echo "# resize --preallocation=falloc" 752_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k 753$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k 754$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 755$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io 756 757echo "# resize --preallocation=full" 758_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k 759$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k 760$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 761$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io 762 763echo 764echo "### Image resizing with preallocation without backing files ###" 765echo 766# In this case the new subclusters must have the 'all zeroes' bit set 767echo "# resize --preallocation=metadata" 768_make_test_img -o extended_l2=on 503k 769$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 770$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k 771$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 772$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io 773 774# In this case and the next one the new subclusters must be allocated 775echo "# resize --preallocation=falloc" 776_make_test_img -o extended_l2=on 503k 777$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 778$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k 779$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 780$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io 781 782echo "# resize --preallocation=full" 783_make_test_img -o extended_l2=on 503k 784$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 785$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k 786$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io 787$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io 788 789echo 790echo "### qemu-img measure ###" 791echo 792echo "# 512MB, extended_l2=off" # This needs one L2 table 793$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=off 794echo "# 512MB, extended_l2=on" # This needs two L2 tables 795$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=on 796 797echo "# 16K clusters, 64GB, extended_l2=off" # This needs one full L1 table cluster 798$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=off 799echo "# 16K clusters, 64GB, extended_l2=on" # This needs two full L2 table clusters 800$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=on 801 802echo "# 8k clusters" # This should fail 803$QEMU_IMG measure --size 1M -O qcow2 -o cluster_size=8k,extended_l2=on 804 805echo "# 1024 TB" # Maximum allowed size with extended_l2=on and 64K clusters 806$QEMU_IMG measure --size 1024T -O qcow2 -o extended_l2=on 807echo "# 1025 TB" # This should fail 808$QEMU_IMG measure --size 1025T -O qcow2 -o extended_l2=on 809 810echo 811echo "### qemu-img amend ###" 812echo 813_make_test_img -o extended_l2=on 1M 814$QEMU_IMG amend -o extended_l2=off "$TEST_IMG" && echo "Unexpected pass" 815 816_make_test_img -o extended_l2=off 1M 817$QEMU_IMG amend -o extended_l2=on "$TEST_IMG" && echo "Unexpected pass" 818 819echo 820echo "### Test copy-on-write on an image with snapshots ###" 821echo 822_make_test_img -o extended_l2=on 1M 823 824# For each cluster from #0 to #9 this loop zeroes subcluster #7 825# and allocates subclusters #13 and #18. 826alloc="13 18"; zero="7" 827for c in $(seq 0 9); do 828 $QEMU_IO -c "write -q -z $((64*$c+14))k 2k" \ 829 -c "write -q -P $((0xd0+$c)) $((64*$c+26))k 2k" \ 830 -c "write -q -P $((0xe0+$c)) $((64*$c+36))k 2k" "$TEST_IMG" 831 _verify_l2_bitmap "$c" 832done 833 834# Create a snapshot and set l2_offset to the new L2 table 835$QEMU_IMG snapshot -c snap1 "$TEST_IMG" 836l2_offset=$((0x110000)) 837 838# Write different patterns to each one of the clusters 839# in order to see how copy-on-write behaves in each case. 840$QEMU_IO -c "write -q -P 0xf0 $((64*0+30))k 1k" \ 841 -c "write -q -P 0xf1 $((64*1+20))k 1k" \ 842 -c "write -q -P 0xf2 $((64*2+40))k 1k" \ 843 -c "write -q -P 0xf3 $((64*3+26))k 1k" \ 844 -c "write -q -P 0xf4 $((64*4+14))k 1k" \ 845 -c "write -q -P 0xf5 $((64*5+1))k 1k" \ 846 -c "write -q -z $((64*6+30))k 3k" \ 847 -c "write -q -z $((64*7+26))k 2k" \ 848 -c "write -q -z $((64*8+26))k 1k" \ 849 -c "write -q -z $((64*9+12))k 1k" \ 850 "$TEST_IMG" 851alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 0 852alloc="$(seq 10 18)"; zero="7" _verify_l2_bitmap 1 853alloc="$(seq 13 20)"; zero="7" _verify_l2_bitmap 2 854alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 3 855alloc="$(seq 7 18)"; zero="" _verify_l2_bitmap 4 856alloc="$(seq 0 18)"; zero="" _verify_l2_bitmap 5 857alloc="13 18"; zero="7 15 16" _verify_l2_bitmap 6 858alloc="18"; zero="7 13" _verify_l2_bitmap 7 859alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 8 860alloc="13 18"; zero="6 7" _verify_l2_bitmap 9 861 862echo 863echo "### Test concurrent requests ###" 864echo 865 866_concurrent_io() 867{ 868# Allocate three subclusters in the same cluster. 869# This works because handle_dependencies() checks whether the requests 870# allocate the same cluster, even if the COW regions don't overlap (in 871# this case they don't). 872cat <<EOF 873open -o driver=$IMGFMT blkdebug::$TEST_IMG 874break write_aio A 875aio_write -P 10 30k 2k 876wait_break A 877aio_write -P 11 20k 2k 878aio_write -P 12 40k 2k 879resume A 880aio_flush 881EOF 882} 883 884_concurrent_verify() 885{ 886cat <<EOF 887open -o driver=$IMGFMT $TEST_IMG 888read -q -P 10 30k 2k 889read -q -P 11 20k 2k 890read -q -P 12 40k 2k 891EOF 892} 893 894_make_test_img -o extended_l2=on 1M 895_concurrent_io | $QEMU_IO | _filter_qemu_io 896_concurrent_verify | $QEMU_IO | _filter_qemu_io 897 898# success, all done 899echo "*** done" 900rm -f $seq.full 901status=0 902