1#!/usr/bin/env bash 2# group: rw auto quick 3# 4# Test case for preallocated zero clusters in qcow2 5# 6# Copyright (C) 2013 Red Hat, Inc. 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=hreitz@redhat.com 24 25seq="$(basename $0)" 26echo "QA output created by $seq" 27 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# We need zero clusters and snapshots 44# (TODO: Consider splitting the snapshot part into a separate test 45# file, so this one runs with refcount_bits=1 and data_file) 46_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file 47 48# Intentionally create an unaligned image 49IMG_SIZE=$((64 * 1024 * 1024 + 512)) 50 51echo 52echo "=== Testing cluster discards ===" 53echo 54_make_test_img $IMG_SIZE 55# Write some normal clusters, zero some of them (creating preallocated 56# zero clusters) and discard everything. Everything should now read as 0. 57$QEMU_IO -c "write 0 256k" -c "write -z 0 256k" -c "write 64M 512" \ 58 -c "discard 0 $IMG_SIZE" -c "read -P 0 0 $IMG_SIZE" "$TEST_IMG" \ 59 | _filter_qemu_io 60 61# Check the image (there shouldn't be any leaks) 62_check_test_img 63# Map the image (we want all clusters to be gone) 64$QEMU_IMG map "$TEST_IMG" 65 66_cleanup_test_img 67 68 69echo 70echo '=== Writing to preallocated zero clusters ===' 71echo 72 73_make_test_img $IMG_SIZE 74 75# Create data clusters (not aligned to an L2 table) 76$QEMU_IO -c 'write -P 42 1M 256k' "$TEST_IMG" | _filter_qemu_io 77orig_map=$($QEMU_IMG map --output=json "$TEST_IMG") 78 79# Convert the data clusters to preallocated zero clusters 80$QEMU_IO -c 'write -z 1M 256k' "$TEST_IMG" | _filter_qemu_io 81 82# Now write to them (with a COW needed for the head and tail) 83$QEMU_IO -c "write -P 23 $(((1024 + 32) * 1024)) 192k" "$TEST_IMG" \ 84 | _filter_qemu_io 85 86# Check metadata correctness 87_check_test_img 88 89# Check data correctness 90$QEMU_IO -c "read -P 0 $(( 1024 * 1024)) 32k" \ 91 -c "read -P 23 $(((1024 + 32) * 1024)) 192k" \ 92 -c "read -P 0 $(((1024 + 32 + 192) * 1024)) 32k" \ 93 "$TEST_IMG" \ 94 | _filter_qemu_io 95 96# Check that we have actually reused the original area 97new_map=$($QEMU_IMG map --output=json "$TEST_IMG") 98if [ "$new_map" = "$orig_map" ]; then 99 echo 'Successfully reused original clusters.' 100else 101 echo 'Failed to reuse original clusters.' 102 echo 'Original map:' 103 echo "$orig_map" 104 echo 'New map:' 105 echo "$new_map" 106fi 107 108_cleanup_test_img 109 110 111echo 112echo '=== Writing to a snapshotted preallocated zero cluster ===' 113echo 114 115_make_test_img 64k 116 117# Create a preallocated zero cluster 118$QEMU_IO -c 'write -P 42 0 64k' -c 'write -z 0 64k' "$TEST_IMG" \ 119 | _filter_qemu_io 120 121# Snapshot it 122$QEMU_IMG snapshot -c foo "$TEST_IMG" 123 124# Write to the cluster 125$QEMU_IO -c 'write -P 23 0 64k' "$TEST_IMG" | _filter_qemu_io 126 127# Check metadata correctness 128_check_test_img 129 130# Check data correctness 131$QEMU_IO -c 'read -P 23 0 64k' "$TEST_IMG" | _filter_qemu_io 132$QEMU_IMG snapshot -a foo "$TEST_IMG" 133$QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io 134 135_cleanup_test_img 136 137 138echo 139echo '=== Consecutive write to a preallocated zero cluster ===' 140echo 141 142_make_test_img 192k 143 144# Create three normal clusters 145$QEMU_IO -c 'write -P 42 0 192k' "$TEST_IMG" | _filter_qemu_io 146orig_map=$($QEMU_IMG map --output=json "$TEST_IMG") 147 148# Make the middle cluster a preallocated zero cluster 149$QEMU_IO -c 'write -z 64k 64k' "$TEST_IMG" | _filter_qemu_io 150 151# Try to overwrite everything: This should reuse the whole range. To test that 152# this only issues a single continuous write request, use blkdebug. 153$QEMU_IO -c 'write -P 42 0 192k' \ 154 "json:{ 155 'driver': '$IMGFMT', 156 'file': { 157 'driver': 'blkdebug', 158 'image.filename': '$TEST_IMG', 159 'set-state': [{ 160 'event': 'write_aio', 161 'new_state': 2 162 }], 163 'inject-error': [{ 164 'event': 'write_aio', 165 'state': 2 166 }] 167 } 168 }" \ 169 | _filter_qemu_io 170 171# Check metadata correctness 172_check_test_img 173 174# Check that we have actually reused the original area 175new_map=$($QEMU_IMG map --output=json "$TEST_IMG") 176if [ "$new_map" = "$orig_map" ]; then 177 echo 'Successfully reused original clusters.' 178else 179 echo 'Failed to reuse original clusters.' 180 echo 'Original map:' 181 echo "$orig_map" 182 echo 'New map:' 183 echo "$new_map" 184fi 185 186_cleanup_test_img 187 188 189# success, all done 190echo "*** done" 191rm -f $seq.full 192status=0 193