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