1#!/bin/bash 2# 3# Test for configuring cache modes of arbitrary nodes (requires O_DIRECT) 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=kwolf@redhat.com 23 24seq=`basename $0` 25echo "QA output created by $seq" 26 27here=`pwd` 28tmp=/tmp/$$ 29status=1 # failure is the default! 30 31_cleanup() 32{ 33 _cleanup_test_img 34 rm -f $TEST_IMG.snap 35} 36trap "_cleanup; exit \$status" 0 1 2 3 15 37 38# get standard environment, filters and checks 39. ./common.rc 40. ./common.filter 41 42_supported_fmt qcow2 43_supported_proto file 44_supported_os Linux 45 46# We test all cache modes anyway, but O_DIRECT needs to be supported 47_default_cache_mode none 48_supported_cache_modes none directsync 49 50function do_run_qemu() 51{ 52 echo Testing: "$@" 53 ( 54 if ! test -t 0; then 55 while read cmd; do 56 echo $cmd 57 done 58 fi 59 echo quit 60 ) | $QEMU -nographic -monitor stdio -nodefaults "$@" 61 echo 62} 63 64function run_qemu() 65{ 66 do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu 67} 68 69size=128M 70 71TEST_IMG="$TEST_IMG.base" _make_test_img $size 72TEST_IMG="$TEST_IMG.snap" _make_test_img $size 73_make_test_img -b "$TEST_IMG.base" $size 74 75echo 76echo === Simple test for all cache modes === 77echo 78 79run_qemu -drive file="$TEST_IMG",cache=none 80run_qemu -drive file="$TEST_IMG",cache=directsync 81run_qemu -drive file="$TEST_IMG",cache=writeback 82run_qemu -drive file="$TEST_IMG",cache=writethrough 83run_qemu -drive file="$TEST_IMG",cache=unsafe 84run_qemu -drive file="$TEST_IMG",cache=invalid_value 85 86echo 87echo === Check inheritance of cache modes === 88echo 89 90files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base" 91ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file" 92 93function check_cache_all() 94{ 95 # cache.direct is supposed to be inherited by both bs->file and 96 # bs->backing 97 98 echo -e "cache.direct=on on none0" 99 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.direct=on | grep "Cache" 100 echo -e "\ncache.direct=on on file" 101 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.direct=on | grep "Cache" 102 echo -e "\ncache.direct=on on backing" 103 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.direct=on | grep "Cache" 104 echo -e "\ncache.direct=on on backing-file" 105 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.direct=on | grep "Cache" 106 107 # cache.writeback is supposed to be inherited by bs->backing; bs->file 108 # always gets cache.writeback=on 109 110 echo -e "\n\ncache.writeback=off on none0" 111 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.writeback=off | grep "Cache" 112 echo -e "\ncache.writeback=off on file" 113 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.writeback=off | grep "Cache" 114 echo -e "\ncache.writeback=off on backing" 115 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.writeback=off | grep "Cache" 116 echo -e "\ncache.writeback=off on backing-file" 117 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.writeback=off | grep "Cache" 118 119 # cache.no-flush is supposed to be inherited by both bs->file and bs->backing 120 121 echo -e "\n\ncache.no-flush=on on none0" 122 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.no-flush=on | grep "Cache" 123 echo -e "\ncache.no-flush=on on file" 124 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.no-flush=on | grep "Cache" 125 echo -e "\ncache.no-flush=on on backing" 126 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.no-flush=on | grep "Cache" 127 echo -e "\ncache.no-flush=on on backing-file" 128 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.no-flush=on | grep "Cache" 129} 130 131echo 132echo "--- Configure cache modes on the command line ---" 133echo 134 135# First check the inherited cache mode after opening the image. 136 137hmp_cmds="info block image 138info block file 139info block backing 140info block backing-file" 141 142check_cache_all 143 144echo 145echo "--- Cache modes after reopen (live snapshot) ---" 146echo 147 148# Then trigger a reopen and check that the cache modes are still the same. 149 150hmp_cmds="snapshot_blkdev -n none0 $TEST_IMG.snap $IMGFMT 151info block 152info block image 153info block file 154info block backing 155info block backing-file" 156 157check_cache_all 158 159echo 160echo "--- Change cache modes with reopen (qemu-io command, flags) ---" 161echo 162 163# This one actually changes the cache mode with the reopen. For this test, the 164# new cache mode is specified in the flags, not as an option. 165 166hmp_cmds='qemu-io none0 "reopen -c none" 167info block image 168info block file 169info block backing 170info block backing-file' 171 172check_cache_all 173 174echo 175echo "--- Change cache modes with reopen (qemu-io command, options) ---" 176echo 177 178# This one actually changes the cache mode with the reopen. For this test, the 179# new cache mode is specified as an option, not in the flags. 180 181hmp_cmds='qemu-io none0 "reopen -o cache.direct=on" 182info block image 183info block file 184info block backing 185info block backing-file' 186 187check_cache_all 188 189echo 190echo "--- Change cache modes after snapshot ---" 191echo 192 193# This checks that the original image doesn't inherit from the snapshot 194 195hmp_cmds="snapshot_blkdev -n none0 $TEST_IMG.snap $IMGFMT 196qemu-io none0 \"reopen -c none\" 197info block none0 198info block image 199info block file 200info block backing 201info block backing-file" 202 203check_cache_all 204 205echo 206echo "--- Change cache mode in parent, child has explicit option in JSON ---" 207echo 208 209# This checks that children with options explicitly set by the json: 210# pseudo-protocol don't inherit these options from their parents. 211# 212# Yes, blkdebug::json:... is criminal, but I can't see another way to have a 213# BDS initialised with the json: pseudo-protocol, but still have it inherit 214# options from its parent node. 215 216hmp_cmds="qemu-io none0 \"reopen -o cache.writeback=off,cache.direct=on,cache.no-flush=on\" 217info block image 218info block blkdebug 219info block file" 220 221echo "$hmp_cmds" | run_qemu -drive if=none,file="blkdebug::json:{\"filename\":\"$TEST_IMG\",,\"cache\":{\"writeback\":false,,\"direct\":false}}",node-name=image,file.node-name=blkdebug,file.image.node-name=file | grep "Cache" 222 223echo 224echo "=== Check that referenced BDSes don't inherit ===" 225echo 226 227drv_bkfile="if=none,driver=file,filename=$TEST_IMG.base,node-name=backing-file" 228drv_bk="if=none,file=json:{'driver':'$IMGFMT',,'file':'backing-file',,'node-name':'backing'}" 229drv_file="if=none,driver=file,filename=$TEST_IMG,node-name=file" 230drv_img="if=none,id=blk,file=json:{'driver':'$IMGFMT',,'file':'file',,'backing':'backing',,'node-name':'image'}" 231 232function check_cache_all_separate() 233{ 234 # Check cache.direct 235 236 echo -e "cache.direct=on on blk" 237 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.direct=on | grep "Cache" 238 echo -e "\ncache.direct=on on file" 239 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.direct=on -drive "$drv_img" | grep "Cache" 240 echo -e "\ncache.direct=on on backing" 241 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.direct=on -drive "$drv_file" -drive "$drv_img" | grep "Cache" 242 echo -e "\ncache.direct=on on backing-file" 243 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.direct=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep "Cache" 244 245 # Check cache.writeback 246 247 echo -e "\n\ncache.writeback=off on blk" 248 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.writeback=off | grep "Cache" 249 echo -e "\ncache.writeback=off on file" 250 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.writeback=off -drive "$drv_img" | grep "Cache" 251 echo -e "\ncache.writeback=off on backing" 252 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.writeback=off -drive "$drv_file" -drive "$drv_img" | grep "Cache" 253 echo -e "\ncache.writeback=off on backing-file" 254 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.writeback=off -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep "Cache" 255 256 # Check cache.no-flush 257 258 echo -e "\n\ncache.no-flush=on on blk" 259 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.no-flush=on | grep "Cache" 260 echo -e "\ncache.no-flush=on on file" 261 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.no-flush=on -drive "$drv_img" | grep "Cache" 262 echo -e "\ncache.no-flush=on on backing" 263 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.no-flush=on -drive "$drv_file" -drive "$drv_img" | grep "Cache" 264 echo -e "\ncache.no-flush=on on backing-file" 265 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.no-flush=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep "Cache" 266} 267 268echo 269echo "--- Configure cache modes on the command line ---" 270echo 271 272# First check the inherited cache mode after opening the image. 273 274hmp_cmds="info block image 275info block file 276info block backing 277info block backing-file" 278 279check_cache_all_separate 280 281echo 282echo "--- Cache modes after reopen (live snapshot) ---" 283echo 284 285# Then trigger a reopen and check that the cache modes are still the same. 286 287hmp_cmds="snapshot_blkdev -n blk $TEST_IMG.snap $IMGFMT 288info block blk 289info block image 290info block file 291info block backing 292info block backing-file" 293 294check_cache_all_separate 295 296echo 297echo "--- Change cache modes with reopen (qemu-io command, flags) ---" 298echo 299 300# This one actually changes the cache mode with the reopen. For this test, the 301# new cache mode is specified as flags, not as option. 302 303hmp_cmds='qemu-io blk "reopen -c none" 304info block image 305info block file 306info block backing 307info block backing-file' 308 309check_cache_all_separate 310 311 312echo 313echo "=== Reopening children instead of the root ===" 314echo 315 316files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base" 317ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file" 318 319echo 320echo "--- Basic reopen ---" 321echo 322 323hmp_cmds='qemu-io none0 "reopen -o backing.cache.direct=on" 324info block image 325info block file 326info block backing 327info block backing-file' 328 329check_cache_all 330 331echo 332echo "--- Change cache mode after reopening child ---" 333echo 334 335# This checks that children with options explicitly set with reopen don't 336# inherit these options from their parents any more 337 338# TODO Implement node-name support for 'qemu-io' HMP command for -c 339# Can use only -o to access child node options for now 340 341hmp_cmds="qemu-io none0 \"reopen -o file.cache.writeback=off,file.cache.direct=off,file.cache.no-flush=off\" 342qemu-io none0 \"reopen -o backing.file.cache.writeback=on,backing.file.cache.direct=off,backing.file.cache.no-flush=on\" 343qemu-io none0 \"reopen -c none\" 344info block image 345info block file 346info block backing 347info block backing-file" 348 349echo "$hmp_cmds" | run_qemu -drive "$files","$ids" | grep "Cache" 350 351# success, all done 352echo "*** done" 353rm -f $seq.full 354status=0 355