xref: /openbmc/qemu/tests/qemu-iotests/112 (revision a9ded601)
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