1#!/usr/bin/env 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 27status=1 # failure is the default! 28 29_cleanup() 30{ 31 _cleanup_test_img 32 _rm_test_img "$TEST_IMG.snap" 33} 34trap "_cleanup; exit \$status" 0 1 2 3 15 35 36# get standard environment, filters and checks 37. ./common.rc 38. ./common.filter 39 40_supported_fmt qcow2 41_supported_proto file 42 43# We test all cache modes anyway, but O_DIRECT needs to be supported 44_default_cache_mode none 45_supported_cache_modes none directsync 46 47do_run_qemu() 48{ 49 echo Testing: "$@" 50 ( 51 if ! test -t 0; then 52 while read cmd; do 53 echo $cmd 54 done 55 fi 56 echo quit 57 ) | $QEMU -nographic -monitor stdio -nodefaults "$@" 58 echo 59} 60 61run_qemu() 62{ 63 do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp 64} 65 66size=128M 67 68TEST_IMG="$TEST_IMG.base" _make_test_img $size 69TEST_IMG="$TEST_IMG.snap" _make_test_img $size 70_make_test_img -b "$TEST_IMG.base" $size -F $IMGFMT 71 72echo 73echo === Simple test for all cache modes === 74echo 75 76run_qemu -drive file="$TEST_IMG",cache=none 77run_qemu -drive file="$TEST_IMG",cache=directsync 78run_qemu -drive file="$TEST_IMG",cache=writeback 79run_qemu -drive file="$TEST_IMG",cache=writethrough 80run_qemu -drive file="$TEST_IMG",cache=unsafe 81run_qemu -drive file="$TEST_IMG",cache=invalid_value 82 83echo 84echo === Check inheritance of cache modes === 85echo 86 87files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base" 88ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file" 89 90check_cache_all() 91{ 92 # cache.direct is supposed to be inherited by both bs->file and 93 # bs->backing 94 95 printf "cache.direct=on on none0\n" 96 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" 97 printf "\ncache.direct=on on file\n" 98 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" 99 printf "\ncache.direct=on on backing\n" 100 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" 101 printf "\ncache.direct=on on backing-file\n" 102 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't" 103 104 # cache.writeback is supposed to be inherited by bs->backing; bs->file 105 # always gets cache.writeback=on 106 107 printf "\n\ncache.writeback=off on none0\n" 108 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 109 printf "\ncache.writeback=off on file\n" 110 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.writeback=off | grep -e "doesn't" -e "does not" 111 printf "\ncache.writeback=off on backing\n" 112 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.writeback=off | grep -e "doesn't" -e "does not" 113 printf "\ncache.writeback=off on backing-file\n" 114 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.writeback=off | grep -e "doesn't" -e "does not" 115 116 # cache.no-flush is supposed to be inherited by both bs->file and bs->backing 117 118 printf "\n\ncache.no-flush=on on none0\n" 119 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 120 printf "\ncache.no-flush=on on file\n" 121 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 122 printf "\ncache.no-flush=on on backing\n" 123 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 124 printf "\ncache.no-flush=on on backing-file\n" 125 echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 126} 127 128echo 129echo "--- Configure cache modes on the command line ---" 130echo 131 132# First check the inherited cache mode after opening the image. 133 134hmp_cmds="info block none0 135info block image 136info block file 137info block backing 138info block backing-file" 139 140check_cache_all 141 142echo 143echo "--- Cache modes after reopen (live snapshot) ---" 144echo 145 146# Then trigger a reopen and check that the cache modes are still the same. 147 148hmp_cmds="snapshot_blkdev -n none0 $TEST_IMG.snap $IMGFMT 149info block 150info block image 151info block file 152info block backing 153info block backing-file" 154 155check_cache_all 156 157echo 158echo "--- Change cache modes with reopen (qemu-io command, flags) ---" 159echo 160 161# This one actually changes the cache mode with the reopen. For this test, the 162# new cache mode is specified in the flags, not as an option. 163 164hmp_cmds='qemu-io none0 "reopen -c none" 165info block none0 166info block image 167info block file 168info block backing 169info block backing-file' 170 171check_cache_all 172 173echo 174echo "--- Change cache modes with reopen (qemu-io command, options) ---" 175echo 176 177# This one actually changes the cache mode with the reopen. For this test, the 178# new cache mode is specified as an option, not in the flags. 179 180hmp_cmds='qemu-io none0 "reopen -o cache.direct=on" 181info block none0 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.direct=on,cache.no-flush=on\" 217info block none0 218info block image 219info block blkdebug 220info block file" 221 222echo "$hmp_cmds" | run_qemu -drive if=none,file="blkdebug::json:{\"filename\":\"$TEST_IMG\",,\"cache\":{\"direct\":false}}",node-name=image,file.node-name=blkdebug,file.image.node-name=file | grep "Cache" 223 224echo 225echo "=== Check that referenced BDSes don't inherit ===" 226echo 227 228drv_bkfile="if=none,driver=file,filename=$TEST_IMG.base,node-name=backing-file" 229drv_bk="if=none,file=json:{'driver':'$IMGFMT',,'file':'backing-file',,'node-name':'backing'}" 230drv_file="if=none,driver=file,filename=$TEST_IMG,node-name=file" 231drv_img="if=none,id=blk,file=json:{'driver':'$IMGFMT',,'file':'file',,'backing':'backing',,'node-name':'image'}" 232 233check_cache_all_separate() 234{ 235 # Check cache.direct 236 237 printf "cache.direct=on on blk\n" 238 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.direct=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 239 printf "\ncache.direct=on on file\n" 240 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.direct=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 241 printf "\ncache.direct=on on backing\n" 242 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.direct=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 243 printf "\ncache.direct=on on backing-file\n" 244 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.direct=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 245 246 # Check cache.writeback 247 248 printf "\n\ncache.writeback=off on blk\n" 249 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 250 printf "\ncache.writeback=off on file\n" 251 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.writeback=off -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 252 printf "\ncache.writeback=off on backing\n" 253 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.writeback=off -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 254 printf "\ncache.writeback=off on backing-file\n" 255 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.writeback=off -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 256 257 # Check cache.no-flush 258 259 printf "\n\ncache.no-flush=on on blk\n" 260 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 261 printf "\ncache.no-flush=on on file\n" 262 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.no-flush=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 263 printf "\ncache.no-flush=on on backing\n" 264 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.no-flush=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 265 printf "\ncache.no-flush=on on backing-file\n" 266 echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.no-flush=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't" 267} 268 269echo 270echo "--- Configure cache modes on the command line ---" 271echo 272 273# First check the inherited cache mode after opening the image. 274 275hmp_cmds="info block image 276info block file 277info block backing 278info block backing-file" 279 280check_cache_all_separate 281 282echo 283echo "--- Cache modes after reopen (live snapshot) ---" 284echo 285 286# Then trigger a reopen and check that the cache modes are still the same. 287 288hmp_cmds="snapshot_blkdev -n blk $TEST_IMG.snap $IMGFMT 289info block blk 290info block image 291info block file 292info block backing 293info block backing-file" 294 295check_cache_all_separate 296 297echo 298echo "--- Change cache modes with reopen (qemu-io command, flags) ---" 299echo 300 301# This one actually changes the cache mode with the reopen. For this test, the 302# new cache mode is specified as flags, not as option. 303 304hmp_cmds='qemu-io blk "reopen -c none" 305info block image 306info block file 307info block backing 308info block backing-file' 309 310check_cache_all_separate 311 312 313echo 314echo "=== Reopening children instead of the root ===" 315echo 316 317files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base" 318ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file" 319 320echo 321echo "--- Basic reopen ---" 322echo 323 324hmp_cmds='qemu-io none0 "reopen -o backing.cache.direct=on" 325info block none0 326info block image 327info block file 328info block backing 329info block backing-file' 330 331check_cache_all 332 333echo 334echo "--- Change cache mode after reopening child ---" 335echo 336 337# This checks that children with options explicitly set with reopen don't 338# inherit these options from their parents any more 339 340# TODO Implement node-name support for 'qemu-io' HMP command for -c 341# Can use only -o to access child node options for now 342 343hmp_cmds="qemu-io none0 \"reopen -o file.cache.direct=off,file.cache.no-flush=off\" 344qemu-io none0 \"reopen -o backing.file.cache.direct=off,backing.file.cache.no-flush=on\" 345qemu-io none0 \"reopen -c none\" 346info block image 347info block file 348info block backing 349info block backing-file" 350 351echo "$hmp_cmds" | run_qemu -drive "$files","$ids" | grep "Cache" 352 353echo 354echo "--- Alignment after changing O_DIRECT ---" 355echo 356 357# Directly test the protocol level: Can unaligned requests succeed even if 358# O_DIRECT was only enabled through a reopen and vice versa? 359 360# Ensure image size is a multiple of the sector size (required for O_DIRECT) 361$QEMU_IMG create -f file "$TEST_IMG" 1M | _filter_img_create 362 363# And write some data (not strictly necessary, but it feels better to actually 364# have something to be read) 365$QEMU_IO -f file -c 'write 0 4096' "$TEST_IMG" | _filter_qemu_io 366 367$QEMU_IO --cache=writeback -f file $TEST_IMG <<EOF | _filter_qemu_io 368read 42 42 369reopen -o cache.direct=on 370read 42 42 371reopen -o cache.direct=off 372read 42 42 373EOF 374$QEMU_IO --cache=none -f file $TEST_IMG <<EOF | _filter_qemu_io 375read 42 42 376reopen -o cache.direct=off 377read 42 42 378reopen -o cache.direct=on 379read 42 42 380EOF 381 382# success, all done 383echo "*** done" 384rm -f $seq.full 385status=0 386