1#!/bin/bash 2# 3# Test exiting qemu while jobs are still running 4# 5# Copyright (C) 2017 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=kwolf@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 rm -f "${TEST_IMG}.mid" 33 rm -f "${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,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,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,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,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 "return" 188 189# If we don't sleep here 'quit' command races with disk I/O 190sleep 0.5 191 192_send_qemu_cmd $h "{ 'execute': 'quit' }" "return" 193wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' 194 195echo 196echo === Start streaming job and exit qemu === 197echo 198 199_launch_qemu \ 200 -drive file="${TEST_IMG}",cache=$CACHEMODE,driver=$IMGFMT,id=disk 201h=$QEMU_HANDLE 202_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" 'return' 203 204_send_qemu_cmd $h \ 205 "{ 'execute': 'block-stream', 206 'arguments': { 'device': 'disk', 207 'speed': 65536 } }" \ 208 "return" 209 210# If we don't sleep here 'quit' command races with disk I/O 211sleep 0.5 212 213_send_qemu_cmd $h "{ 'execute': 'quit' }" "return" 214wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' 215 216_check_test_img 217 218# success, all done 219echo "*** done" 220rm -f $seq.full 221status=0 222