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