1#!/bin/bash 2# 3# Test cases for different refcount_bits values 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=mreitz@redhat.com 23 24seq="$(basename $0)" 25echo "QA output created by $seq" 26 27here="$PWD" 28status=1 # failure is the default! 29 30_cleanup() 31{ 32 _cleanup_test_img 33} 34trap "_cleanup; exit \$status" 0 1 2 3 15 35 36# get standard environment, filters and checks 37. ./common.rc 38. ./common.filter 39 40# This tests qcow2-specific low-level functionality 41_supported_fmt qcow2 42_supported_proto file 43_supported_os Linux 44# This test will set refcount_bits on its own which would conflict with the 45# manual setting; compat will be overridden as well 46_unsupported_imgopts refcount_bits 'compat=0.10' 47 48function print_refcount_bits() 49{ 50 $QEMU_IMG info "$TEST_IMG" | sed -n '/refcount bits:/ s/^ *//p' 51} 52 53echo 54echo '=== refcount_bits limits ===' 55echo 56 57# Must be positive (non-zero) 58IMGOPTS="$IMGOPTS,refcount_bits=0" _make_test_img 64M 59# Must be positive (non-negative) 60IMGOPTS="$IMGOPTS,refcount_bits=-1" _make_test_img 64M 61# May not exceed 64 62IMGOPTS="$IMGOPTS,refcount_bits=128" _make_test_img 64M 63# Must be a power of two 64IMGOPTS="$IMGOPTS,refcount_bits=42" _make_test_img 64M 65 66# 1 is the minimum 67IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M 68print_refcount_bits 69 70# 64 is the maximum 71IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M 72print_refcount_bits 73 74# 16 is the default 75_make_test_img 64M 76print_refcount_bits 77 78echo 79echo '=== refcount_bits and compat=0.10 ===' 80echo 81 82# Should work 83IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=16" _make_test_img 64M 84print_refcount_bits 85 86# Should not work 87IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=1" _make_test_img 64M 88IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=64" _make_test_img 64M 89 90 91echo 92echo '=== Snapshot limit on refcount_bits=1 ===' 93echo 94 95IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M 96print_refcount_bits 97 98$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io 99 100# Should fail for now; in the future, this might be supported by automatically 101# copying all clusters with overflowing refcount 102$QEMU_IMG snapshot -c foo "$TEST_IMG" 103 104# The new L1 table could/should be leaked 105_check_test_img 106 107echo 108echo '=== Snapshot limit on refcount_bits=2 ===' 109echo 110 111IMGOPTS="$IMGOPTS,refcount_bits=2" _make_test_img 64M 112print_refcount_bits 113 114$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io 115 116# Should succeed 117$QEMU_IMG snapshot -c foo "$TEST_IMG" 118$QEMU_IMG snapshot -c bar "$TEST_IMG" 119# Should fail (4th reference) 120$QEMU_IMG snapshot -c baz "$TEST_IMG" 121 122# The new L1 table could/should be leaked 123_check_test_img 124 125echo 126echo '=== Compressed clusters with refcount_bits=1 ===' 127echo 128 129IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M 130print_refcount_bits 131 132# Both should fit into a single host cluster; instead of failing to increase the 133# refcount of that cluster, qemu should just allocate a new cluster and make 134# this operation succeed 135$QEMU_IO -c 'write -P 0 -c 0 64k' \ 136 -c 'write -P 1 -c 64k 64k' \ 137 "$TEST_IMG" | _filter_qemu_io 138 139_check_test_img 140 141echo 142echo '=== MSb set in 64 bit refcount ===' 143echo 144 145IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M 146print_refcount_bits 147 148$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io 149 150# Set the MSb in the refblock entry of the data cluster 151poke_file "$TEST_IMG" $((0x20028)) "\x80\x00\x00\x00\x00\x00\x00\x00" 152 153# Clear OFLAG_COPIED in the L2 entry of the data cluster 154poke_file "$TEST_IMG" $((0x40000)) "\x00\x00\x00\x00\x00\x05\x00\x00" 155 156# Try to write to that cluster (should work, even though the MSb is set) 157$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io 158 159echo 160echo '=== Snapshot on maximum 64 bit refcount value ===' 161echo 162 163IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M 164print_refcount_bits 165 166$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io 167 168# Set the refblock entry to the maximum value possible 169poke_file "$TEST_IMG" $((0x20028)) "\xff\xff\xff\xff\xff\xff\xff\xff" 170 171# Clear OFLAG_COPIED in the L2 entry of the data cluster 172poke_file "$TEST_IMG" $((0x40000)) "\x00\x00\x00\x00\x00\x05\x00\x00" 173 174# Try a snapshot (should correctly identify the overflow; may work in the future 175# by falling back to COW) 176$QEMU_IMG snapshot -c foo "$TEST_IMG" 177 178# The new L1 table could/should be leaked; and obviously the data cluster is 179# leaked (refcount=UINT64_MAX reference=1) 180_check_test_img 181 182echo 183echo '=== Amend from refcount_bits=16 to refcount_bits=1 ===' 184echo 185 186_make_test_img 64M 187print_refcount_bits 188 189$QEMU_IO -c 'write 16M 32M' "$TEST_IMG" | _filter_qemu_io 190$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG" 191_check_test_img 192print_refcount_bits 193 194echo 195echo '=== Amend from refcount_bits=1 to refcount_bits=64 ===' 196echo 197 198$QEMU_IMG amend -o refcount_bits=64 "$TEST_IMG" 199_check_test_img 200print_refcount_bits 201 202echo 203echo '=== Amend to compat=0.10 ===' 204echo 205 206# Should not work because refcount_bits needs to be 16 for compat=0.10 207$QEMU_IMG amend -o compat=0.10 "$TEST_IMG" 208print_refcount_bits 209# Should work 210$QEMU_IMG amend -o compat=0.10,refcount_bits=16 "$TEST_IMG" 211_check_test_img 212print_refcount_bits 213 214# Get back to compat=1.1 and refcount_bits=16 215$QEMU_IMG amend -o compat=1.1 "$TEST_IMG" 216print_refcount_bits 217# Should not work 218$QEMU_IMG amend -o refcount_bits=32,compat=0.10 "$TEST_IMG" 219print_refcount_bits 220 221echo 222echo '=== Amend with snapshot ===' 223echo 224 225$QEMU_IMG snapshot -c foo "$TEST_IMG" 226# Just to have different refcounts across the image 227$QEMU_IO -c 'write 0 16M' "$TEST_IMG" | _filter_qemu_io 228 229# Should not work (may work in the future by first decreasing all refcounts so 230# they fit into the target range by copying them) 231$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG" 232_check_test_img 233print_refcount_bits 234 235# Should work 236$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG" 237_check_test_img 238print_refcount_bits 239 240echo 241echo '=== Testing too many references for check ===' 242echo 243 244IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M 245print_refcount_bits 246 247# This cluster should be created at 0x50000 248$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io 249# Now make the second L2 entry (the L2 table should be at 0x40000) point to that 250# cluster, so we have two references 251poke_file "$TEST_IMG" $((0x40008)) "\x80\x00\x00\x00\x00\x05\x00\x00" 252 253# This should say "please use amend" 254_check_test_img -r all 255 256# So we do that 257$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG" 258print_refcount_bits 259 260# And try again 261_check_test_img -r all 262 263echo 264echo '=== Multiple walks necessary during amend ===' 265echo 266 267IMGOPTS="$IMGOPTS,refcount_bits=1,cluster_size=512" _make_test_img 64k 268 269# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a 270# single L2 table, the reftable and a single refblock. This creates 58 data 271# clusters (actually, the L2 table is created here, too), so in total there are 272# then 63 used clusters in the image. With a refcount width of 64, one refblock 273# describes 64 clusters (512 bytes / 64 bits/entry = 64 entries), so this will 274# make the first refblock in the amended image have exactly one free entry. 275$QEMU_IO -c "write 0 $((58 * 512))" "$TEST_IMG" | _filter_qemu_io 276 277# Now change the refcount width; since the first new refblock will have exactly 278# one free entry, that entry will be used to store its own reference. No other 279# refblocks are needed, so then the new reftable will be allocated; since the 280# first new refblock is completely filled up, this will require a new refblock 281# which is why the refcount width changing function will need to run through 282# everything one more time until the allocations are stable. 283# Having more walks than usual should be visible as regressing progress (from 284# 66.67 % (2/3 walks) to 50.00 % (2/4 walks)). 285$QEMU_IMG amend -o refcount_bits=64 -p "$TEST_IMG" | tr '\r' '\n' \ 286 | grep -A 1 '66.67' 287print_refcount_bits 288 289_check_test_img 290 291 292# success, all done 293echo '*** done' 294rm -f $seq.full 295status=0 296