8cedcffdc1
Bash allows functions to be declared with or without the leading keyword 'function'; but including the keyword does not comply with POSIX syntax, and is confusing to ksh users where the use of the keyword changes the scoping rules for functions. Stick to the POSIX form through iotests. Done mechanically with: sed -i 's/^function //' $(git ls-files tests/qemu-iotests) Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20181116215002.2124581-1-eblake@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
295 lines
8.3 KiB
Bash
Executable File
295 lines
8.3 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Test cases for different refcount_bits values
|
|
#
|
|
# Copyright (C) 2015 Red Hat, Inc.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
# creator
|
|
owner=mreitz@redhat.com
|
|
|
|
seq="$(basename $0)"
|
|
echo "QA output created by $seq"
|
|
|
|
status=1 # failure is the default!
|
|
|
|
_cleanup()
|
|
{
|
|
_cleanup_test_img
|
|
}
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
|
# get standard environment, filters and checks
|
|
. ./common.rc
|
|
. ./common.filter
|
|
|
|
# This tests qcow2-specific low-level functionality
|
|
_supported_fmt qcow2
|
|
_supported_proto file
|
|
_supported_os Linux
|
|
# This test will set refcount_bits on its own which would conflict with the
|
|
# manual setting; compat will be overridden as well
|
|
_unsupported_imgopts refcount_bits 'compat=0.10'
|
|
|
|
print_refcount_bits()
|
|
{
|
|
$QEMU_IMG info "$TEST_IMG" | sed -n '/refcount bits:/ s/^ *//p'
|
|
}
|
|
|
|
echo
|
|
echo '=== refcount_bits limits ==='
|
|
echo
|
|
|
|
# Must be positive (non-zero)
|
|
IMGOPTS="$IMGOPTS,refcount_bits=0" _make_test_img 64M
|
|
# Must be positive (non-negative)
|
|
IMGOPTS="$IMGOPTS,refcount_bits=-1" _make_test_img 64M
|
|
# May not exceed 64
|
|
IMGOPTS="$IMGOPTS,refcount_bits=128" _make_test_img 64M
|
|
# Must be a power of two
|
|
IMGOPTS="$IMGOPTS,refcount_bits=42" _make_test_img 64M
|
|
|
|
# 1 is the minimum
|
|
IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
# 64 is the maximum
|
|
IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
# 16 is the default
|
|
_make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
echo
|
|
echo '=== refcount_bits and compat=0.10 ==='
|
|
echo
|
|
|
|
# Should work
|
|
IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=16" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
# Should not work
|
|
IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=1" _make_test_img 64M
|
|
IMGOPTS="$IMGOPTS,compat=0.10,refcount_bits=64" _make_test_img 64M
|
|
|
|
|
|
echo
|
|
echo '=== Snapshot limit on refcount_bits=1 ==='
|
|
echo
|
|
|
|
IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
|
|
|
|
# Should fail for now; in the future, this might be supported by automatically
|
|
# copying all clusters with overflowing refcount
|
|
$QEMU_IMG snapshot -c foo "$TEST_IMG"
|
|
|
|
# The new L1 table could/should be leaked
|
|
_check_test_img
|
|
|
|
echo
|
|
echo '=== Snapshot limit on refcount_bits=2 ==='
|
|
echo
|
|
|
|
IMGOPTS="$IMGOPTS,refcount_bits=2" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
|
|
|
|
# Should succeed
|
|
$QEMU_IMG snapshot -c foo "$TEST_IMG"
|
|
$QEMU_IMG snapshot -c bar "$TEST_IMG"
|
|
# Should fail (4th reference)
|
|
$QEMU_IMG snapshot -c baz "$TEST_IMG"
|
|
|
|
# The new L1 table could/should be leaked
|
|
_check_test_img
|
|
|
|
echo
|
|
echo '=== Compressed clusters with refcount_bits=1 ==='
|
|
echo
|
|
|
|
IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
# Both should fit into a single host cluster; instead of failing to increase the
|
|
# refcount of that cluster, qemu should just allocate a new cluster and make
|
|
# this operation succeed
|
|
$QEMU_IO -c 'write -P 0 -c 0 64k' \
|
|
-c 'write -P 1 -c 64k 64k' \
|
|
"$TEST_IMG" | _filter_qemu_io
|
|
|
|
_check_test_img
|
|
|
|
echo
|
|
echo '=== MSb set in 64 bit refcount ==='
|
|
echo
|
|
|
|
IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
|
|
|
|
# Set the MSb in the refblock entry of the data cluster
|
|
poke_file "$TEST_IMG" $((0x20028)) "\x80\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
# Clear OFLAG_COPIED in the L2 entry of the data cluster
|
|
poke_file "$TEST_IMG" $((0x40000)) "\x00\x00\x00\x00\x00\x05\x00\x00"
|
|
|
|
# Try to write to that cluster (should work, even though the MSb is set)
|
|
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
|
|
|
|
echo
|
|
echo '=== Snapshot on maximum 64 bit refcount value ==='
|
|
echo
|
|
|
|
IMGOPTS="$IMGOPTS,refcount_bits=64" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
|
|
|
|
# Set the refblock entry to the maximum value possible
|
|
poke_file "$TEST_IMG" $((0x20028)) "\xff\xff\xff\xff\xff\xff\xff\xff"
|
|
|
|
# Clear OFLAG_COPIED in the L2 entry of the data cluster
|
|
poke_file "$TEST_IMG" $((0x40000)) "\x00\x00\x00\x00\x00\x05\x00\x00"
|
|
|
|
# Try a snapshot (should correctly identify the overflow; may work in the future
|
|
# by falling back to COW)
|
|
$QEMU_IMG snapshot -c foo "$TEST_IMG"
|
|
|
|
# The new L1 table could/should be leaked; and obviously the data cluster is
|
|
# leaked (refcount=UINT64_MAX reference=1)
|
|
_check_test_img
|
|
|
|
echo
|
|
echo '=== Amend from refcount_bits=16 to refcount_bits=1 ==='
|
|
echo
|
|
|
|
_make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
$QEMU_IO -c 'write 16M 32M' "$TEST_IMG" | _filter_qemu_io
|
|
$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG"
|
|
_check_test_img
|
|
print_refcount_bits
|
|
|
|
echo
|
|
echo '=== Amend from refcount_bits=1 to refcount_bits=64 ==='
|
|
echo
|
|
|
|
$QEMU_IMG amend -o refcount_bits=64 "$TEST_IMG"
|
|
_check_test_img
|
|
print_refcount_bits
|
|
|
|
echo
|
|
echo '=== Amend to compat=0.10 ==='
|
|
echo
|
|
|
|
# Should not work because refcount_bits needs to be 16 for compat=0.10
|
|
$QEMU_IMG amend -o compat=0.10 "$TEST_IMG"
|
|
print_refcount_bits
|
|
# Should work
|
|
$QEMU_IMG amend -o compat=0.10,refcount_bits=16 "$TEST_IMG"
|
|
_check_test_img
|
|
print_refcount_bits
|
|
|
|
# Get back to compat=1.1 and refcount_bits=16
|
|
$QEMU_IMG amend -o compat=1.1 "$TEST_IMG"
|
|
print_refcount_bits
|
|
# Should not work
|
|
$QEMU_IMG amend -o refcount_bits=32,compat=0.10 "$TEST_IMG"
|
|
print_refcount_bits
|
|
|
|
echo
|
|
echo '=== Amend with snapshot ==='
|
|
echo
|
|
|
|
$QEMU_IMG snapshot -c foo "$TEST_IMG"
|
|
# Just to have different refcounts across the image
|
|
$QEMU_IO -c 'write 0 16M' "$TEST_IMG" | _filter_qemu_io
|
|
|
|
# Should not work (may work in the future by first decreasing all refcounts so
|
|
# they fit into the target range by copying them)
|
|
$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG"
|
|
_check_test_img
|
|
print_refcount_bits
|
|
|
|
# Should work
|
|
$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG"
|
|
_check_test_img
|
|
print_refcount_bits
|
|
|
|
echo
|
|
echo '=== Testing too many references for check ==='
|
|
echo
|
|
|
|
IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
|
|
print_refcount_bits
|
|
|
|
# This cluster should be created at 0x50000
|
|
$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
|
|
# Now make the second L2 entry (the L2 table should be at 0x40000) point to that
|
|
# cluster, so we have two references
|
|
poke_file "$TEST_IMG" $((0x40008)) "\x80\x00\x00\x00\x00\x05\x00\x00"
|
|
|
|
# This should say "please use amend"
|
|
_check_test_img -r all
|
|
|
|
# So we do that
|
|
$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG"
|
|
print_refcount_bits
|
|
|
|
# And try again
|
|
_check_test_img -r all
|
|
|
|
echo
|
|
echo '=== Multiple walks necessary during amend ==='
|
|
echo
|
|
|
|
IMGOPTS="$IMGOPTS,refcount_bits=1,cluster_size=512" _make_test_img 64k
|
|
|
|
# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a
|
|
# single L2 table, the reftable and a single refblock. This creates 58 data
|
|
# clusters (actually, the L2 table is created here, too), so in total there are
|
|
# then 63 used clusters in the image. With a refcount width of 64, one refblock
|
|
# describes 64 clusters (512 bytes / 64 bits/entry = 64 entries), so this will
|
|
# make the first refblock in the amended image have exactly one free entry.
|
|
$QEMU_IO -c "write 0 $((58 * 512))" "$TEST_IMG" | _filter_qemu_io
|
|
|
|
# Now change the refcount width; since the first new refblock will have exactly
|
|
# one free entry, that entry will be used to store its own reference. No other
|
|
# refblocks are needed, so then the new reftable will be allocated; since the
|
|
# first new refblock is completely filled up, this will require a new refblock
|
|
# which is why the refcount width changing function will need to run through
|
|
# everything one more time until the allocations are stable.
|
|
# Having more walks than usual should be visible as regressing progress (from
|
|
# 66.67 % (2/3 walks) to 50.00 % (2/4 walks)).
|
|
$QEMU_IMG amend -o refcount_bits=64 -p "$TEST_IMG" | tr '\r' '\n' \
|
|
| grep -A 1 '66.67'
|
|
print_refcount_bits
|
|
|
|
_check_test_img
|
|
|
|
|
|
# success, all done
|
|
echo '*** done'
|
|
rm -f $seq.full
|
|
status=0
|