xref: /openbmc/qemu/tests/qemu-iotests/185 (revision 96916f36)
1#!/usr/bin/env bash
2# group: rw
3#
4# Test exiting qemu while jobs are still running
5#
6# Copyright (C) 2017 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=kwolf@redhat.com
24
25seq=`basename $0`
26echo "QA output created by $seq"
27
28status=1 # failure is the default!
29
30_cleanup()
31{
32    _rm_test_img "${TEST_IMG}.mid"
33    _rm_test_img "${TEST_IMG}.copy"
34    _cleanup_test_img
35    _cleanup_qemu
36}
37trap "_cleanup; exit \$status" 0 1 2 3 15
38
39# get standard environment, filters and checks
40. ./common.rc
41. ./common.filter
42. ./common.qemu
43
44_supported_fmt qcow2
45_supported_proto file
46_supported_os Linux
47
48size=64M
49TEST_IMG="${TEST_IMG}.base" _make_test_img $size
50
51echo
52echo === Starting VM ===
53echo
54
55qemu_comm_method="qmp"
56
57_launch_qemu \
58    -drive file="${TEST_IMG}.base",cache=$CACHEMODE,aio=$AIOMODE,driver=$IMGFMT,id=disk
59h=$QEMU_HANDLE
60_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return'
61
62echo
63echo === Creating backing chain ===
64echo
65
66_send_qemu_cmd $h \
67    "{ 'execute': 'blockdev-snapshot-sync',
68       'arguments': { 'device': 'disk',
69                      'snapshot-file': '$TEST_IMG.mid',
70                      'format': '$IMGFMT',
71                      'mode': 'absolute-paths' } }" \
72    "return"
73
74_send_qemu_cmd $h \
75    "{ 'execute': 'human-monitor-command',
76       'arguments': { 'command-line':
77                      'qemu-io disk \"write 0 4M\"' } }" \
78    "return"
79
80_send_qemu_cmd $h \
81    "{ 'execute': 'blockdev-snapshot-sync',
82       'arguments': { 'device': 'disk',
83                      'snapshot-file': '$TEST_IMG',
84                      'format': '$IMGFMT',
85                      'mode': 'absolute-paths' } }" \
86    "return"
87
88echo
89echo === Start commit job and exit qemu ===
90echo
91
92# Note that the reference output intentionally includes the 'offset' field in
93# BLOCK_JOB_* events for all of the following block jobs. They are predictable
94# and any change in the offsets would hint at a bug in the job throttling code.
95#
96# In order to achieve these predictable offsets, all of the following tests
97# use speed=65536. Each job will perform exactly one iteration before it has
98# to sleep at least for a second, which is plenty of time for the 'quit' QMP
99# command to be received (after receiving the command, the rest runs
100# synchronously, so jobs can arbitrarily continue or complete).
101#
102# The buffer size for commit and streaming is 512k (waiting for 8 seconds after
103# the first request), for active commit and mirror it's large enough to cover
104# the full 4M, and for backup it's the qcow2 cluster size, which we know is
105# 64k. As all of these are at least as large as the speed, we are sure that the
106# offset advances exactly once before qemu exits.
107
108_send_qemu_cmd $h \
109    "{ 'execute': 'block-commit',
110       'arguments': { 'device': 'disk',
111                      'base':'$TEST_IMG.base',
112                      'top': '$TEST_IMG.mid',
113                      'speed': 65536 } }" \
114    "return"
115
116# If we don't sleep here 'quit' command races with disk I/O
117sleep 0.5
118
119# Ignore the JOB_STATUS_CHANGE events while shutting down the VM. Depending on
120# the timing, jobs may or may not transition through a paused state.
121_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
122wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE'
123
124echo
125echo === Start active commit job and exit qemu ===
126echo
127
128_launch_qemu \
129    -drive file="${TEST_IMG}",cache=$CACHEMODE,aio=$AIOMODE,driver=$IMGFMT,id=disk
130h=$QEMU_HANDLE
131_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return'
132
133_send_qemu_cmd $h \
134    "{ 'execute': 'block-commit',
135       'arguments': { 'device': 'disk',
136                      'base':'$TEST_IMG.base',
137                      'speed': 65536 } }" \
138    "return"
139
140# If we don't sleep here 'quit' command races with disk I/O
141sleep 0.5
142
143_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
144wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE'
145
146echo
147echo === Start mirror job and exit qemu ===
148echo
149
150_launch_qemu \
151    -drive file="${TEST_IMG}",cache=$CACHEMODE,aio=$AIOMODE,driver=$IMGFMT,id=disk
152h=$QEMU_HANDLE
153_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return'
154
155_send_qemu_cmd $h \
156    "{ 'execute': 'drive-mirror',
157       'arguments': { 'device': 'disk',
158                      'target': '$TEST_IMG.copy',
159                      'format': '$IMGFMT',
160                      'sync': 'full',
161                      'speed': 65536 } }" \
162    "return"
163
164# If we don't sleep here 'quit' command may be handled before
165# the first mirror iteration is done
166sleep 0.5
167
168_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
169wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE'
170
171echo
172echo === Start backup job and exit qemu ===
173echo
174
175_launch_qemu \
176    -drive file="${TEST_IMG}",cache=$CACHEMODE,aio=$AIOMODE,driver=$IMGFMT,id=disk
177h=$QEMU_HANDLE
178_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return'
179
180_send_qemu_cmd $h \
181    "{ 'execute': 'drive-backup',
182       'arguments': { 'device': 'disk',
183                      'target': '$TEST_IMG.copy',
184                      'format': '$IMGFMT',
185                      'sync': 'full',
186                      'speed': 65536,
187                      'x-perf': {'max-chunk': 65536} } }" \
188    "return"
189
190# If we don't sleep here 'quit' command races with disk I/O
191sleep 0.5
192
193_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
194wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE'
195
196echo
197echo === Start streaming job and exit qemu ===
198echo
199
200_launch_qemu \
201    -drive file="${TEST_IMG}",cache=$CACHEMODE,aio=$AIOMODE,driver=$IMGFMT,id=disk
202h=$QEMU_HANDLE
203_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return'
204
205_send_qemu_cmd $h \
206    "{ 'execute': 'block-stream',
207       'arguments': { 'device': 'disk',
208                      'speed': 65536 } }" \
209    "return"
210
211# If we don't sleep here 'quit' command races with disk I/O
212sleep 0.5
213
214_send_qemu_cmd $h "{ 'execute': 'quit' }" "return"
215wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE'
216
217_check_test_img
218
219# success, all done
220echo "*** done"
221rm -f $seq.full
222status=0
223