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