1#!/usr/bin/env bash 2# 3# Copyright Red Hat 4# Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <http://www.gnu.org/licenses/>. 18# 19 20export LANG=C 21 22PATH=".:$PATH" 23 24HOSTOS=$(uname -s) 25arch=$(uname -m) 26[[ "$arch" =~ "ppc64" ]] && qemu_arch=ppc64 || qemu_arch="$arch" 27 28# make sure we have a standard umask 29umask 022 30 31# bail out, setting up .notrun file 32_notrun() 33{ 34 echo "$*" >"$TEST_DIR/$seq.notrun" 35 echo "$seq not run: $*" 36 status=0 37 exit 38} 39 40if ! command -v gsed >/dev/null 2>&1; then 41 if sed --version 2>&1 | grep -v 'not GNU sed' | grep 'GNU sed' > /dev/null; 42 then 43 gsed() 44 { 45 sed "$@" 46 } 47 else 48 gsed() 49 { 50 _notrun "GNU sed not available" 51 } 52 fi 53fi 54 55dd() 56{ 57 if [ "$HOSTOS" == "Linux" ] 58 then 59 command dd --help | grep noxfer > /dev/null 2>&1 60 61 if [ "$?" -eq 0 ] 62 then 63 command dd status=noxfer $@ 64 else 65 command dd $@ 66 fi 67 else 68 command dd $@ 69 fi 70} 71 72# poke_file 'test.img' 512 '\xff\xfe' 73poke_file() 74{ 75 printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null 76} 77 78# poke_file_le $img_filename $offset $byte_width $value 79# Example: poke_file_le "$TEST_IMG" 512 2 65534 80poke_file_le() 81{ 82 local img=$1 ofs=$2 len=$3 val=$4 str='' 83 84 while ((len--)); do 85 str+=$(printf '\\x%02x' $((val & 0xff))) 86 val=$((val >> 8)) 87 done 88 89 poke_file "$img" "$ofs" "$str" 90} 91 92# poke_file_be $img_filename $offset $byte_width $value 93# Example: poke_file_be "$TEST_IMG" 512 2 65279 94poke_file_be() 95{ 96 local img=$1 ofs=$2 len=$3 val=$4 97 local str=$(printf "%0$((len * 2))x\n" $val | sed 's/\(..\)/\\x\1/g') 98 99 poke_file "$img" "$ofs" "$str" 100} 101 102# peek_file_le 'test.img' 512 2 => 65534 103peek_file_le() 104{ 105 local val=0 shift=0 byte 106 107 # coreutils' od --endian is not portable, so manually assemble bytes. 108 for byte in $(od -j"$2" -N"$3" -An -v -tu1 "$1"); do 109 val=$(( val | (byte << shift) )) 110 shift=$((shift + 8)) 111 done 112 printf %llu $val 113} 114 115# peek_file_be 'test.img' 512 2 => 65279 116peek_file_be() 117{ 118 local val=0 byte 119 120 # coreutils' od --endian is not portable, so manually assemble bytes. 121 for byte in $(od -j"$2" -N"$3" -An -v -tu1 "$1"); do 122 val=$(( (val << 8) | byte )) 123 done 124 printf %llu $val 125} 126 127# peek_file_raw 'test.img' 512 2 => '\xff\xfe'. Do not use if the raw data 128# is likely to contain \0 or trailing \n. 129peek_file_raw() 130{ 131 dd if="$1" bs=1 skip="$2" count="$3" status=none 132} 133 134_optstr_add() 135{ 136 if [ -n "$1" ]; then 137 echo "$1,$2" 138 else 139 echo "$2" 140 fi 141} 142 143# Set the variables to the empty string to turn Valgrind off 144# for specific processes, e.g. 145# $ VALGRIND_QEMU_IO= ./check -qcow2 -valgrind 015 146 147: ${VALGRIND_QEMU_VM=$VALGRIND_QEMU} 148: ${VALGRIND_QEMU_IMG=$VALGRIND_QEMU} 149: ${VALGRIND_QEMU_IO=$VALGRIND_QEMU} 150: ${VALGRIND_QEMU_NBD=$VALGRIND_QEMU} 151: ${VALGRIND_QSD=$VALGRIND_QEMU} 152 153# The Valgrind own parameters may be set with 154# its environment variable VALGRIND_OPTS, e.g. 155# $ VALGRIND_OPTS="--leak-check=yes" ./check -qcow2 -valgrind 015 156 157_qemu_proc_exec() 158{ 159 local VALGRIND_LOGFILE="$1" 160 shift 161 if [[ "${VALGRIND_QEMU}" == "y" && "${NO_VALGRIND}" != "y" ]]; then 162 exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$@" 163 else 164 exec "$@" 165 fi 166} 167 168_qemu_proc_valgrind_log() 169{ 170 local VALGRIND_LOGFILE="$1" 171 local RETVAL="$2" 172 if [[ "${VALGRIND_QEMU}" == "y" && "${NO_VALGRIND}" != "y" ]]; then 173 if [ $RETVAL == 99 ]; then 174 cat "${VALGRIND_LOGFILE}" 175 fi 176 rm -f "${VALGRIND_LOGFILE}" 177 fi 178} 179 180_qemu_wrapper() 181{ 182 local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind 183 ( 184 if [ -n "${QEMU_NEED_PID}" ]; then 185 echo $BASHPID > "${QEMU_TEST_DIR}/qemu-${_QEMU_HANDLE}.pid" 186 fi 187 188 GDB="" 189 if [ -n "${GDB_OPTIONS}" ]; then 190 GDB="gdbserver ${GDB_OPTIONS}" 191 fi 192 193 VALGRIND_QEMU="${VALGRIND_QEMU_VM}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \ 194 $GDB "$QEMU_PROG" $QEMU_OPTIONS "$@" 195 ) 196 RETVAL=$? 197 _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL 198 return $RETVAL 199} 200 201_qemu_img_wrapper() 202{ 203 local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind 204 ( 205 VALGRIND_QEMU="${VALGRIND_QEMU_IMG}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \ 206 "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS "$@" 207 ) 208 RETVAL=$? 209 _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL 210 return $RETVAL 211} 212 213_qemu_io_wrapper() 214{ 215 local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind 216 local QEMU_IO_ARGS="$QEMU_IO_OPTIONS" 217 if [ "$IMGOPTSSYNTAX" = "true" ]; then 218 QEMU_IO_ARGS="--image-opts $QEMU_IO_ARGS" 219 if [ -n "$IMGKEYSECRET" ]; then 220 QEMU_IO_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IO_ARGS" 221 fi 222 fi 223 ( 224 VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \ 225 "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" 226 ) 227 RETVAL=$? 228 _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL 229 return $RETVAL 230} 231 232_qemu_nbd_wrapper() 233{ 234 local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind 235 ( 236 VALGRIND_QEMU="${VALGRIND_QEMU_NBD}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \ 237 "$QEMU_NBD_PROG" --pid-file="${QEMU_TEST_DIR}/qemu-nbd.pid" \ 238 $QEMU_NBD_OPTIONS "$@" 239 ) 240 RETVAL=$? 241 _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL 242 return $RETVAL 243} 244 245_qemu_storage_daemon_wrapper() 246{ 247 local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind 248 ( 249 if [ -n "${QSD_NEED_PID}" ]; then 250 echo $BASHPID > "${QEMU_TEST_DIR}/qemu-storage-daemon.pid" 251 fi 252 VALGRIND_QEMU="${VALGRIND_QSD}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \ 253 "$QSD_PROG" $QSD_OPTIONS "$@" 254 ) 255 RETVAL=$? 256 _qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL 257 return $RETVAL 258} 259 260# Valgrind bug #409141 https://bugs.kde.org/show_bug.cgi?id=409141 261# Until valgrind 3.16+ is ubiquitous, we must work around a hang in 262# valgrind when issuing sigkill. Disable valgrind for this invocation. 263_NO_VALGRIND() 264{ 265 NO_VALGRIND="y" "$@" 266} 267 268export QEMU=_qemu_wrapper 269export QEMU_IMG=_qemu_img_wrapper 270export QEMU_IO=_qemu_io_wrapper 271export QEMU_NBD=_qemu_nbd_wrapper 272export QSD=_qemu_storage_daemon_wrapper 273 274if [ "$IMGOPTSSYNTAX" = "true" ]; then 275 DRIVER="driver=$IMGFMT" 276 QEMU_IMG_EXTRA_ARGS="--image-opts $QEMU_IMG_EXTRA_ARGS" 277 if [ -n "$IMGKEYSECRET" ]; then 278 QEMU_IMG_EXTRA_ARGS="--object secret,id=keysec0,data=$IMGKEYSECRET $QEMU_IMG_EXTRA_ARGS" 279 fi 280 if [ "$IMGFMT" = "luks" ]; then 281 DRIVER="$DRIVER,key-secret=keysec0" 282 fi 283 if [ "$IMGPROTO" = "file" ]; then 284 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 285 TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT" 286 elif [ "$IMGPROTO" = "nbd" ]; then 287 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 288 TEST_IMG="$DRIVER,file.driver=nbd,file.type=unix" 289 TEST_IMG="$TEST_IMG,file.path=$SOCK_DIR/nbd" 290 elif [ "$IMGPROTO" = "fuse" ]; then 291 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 292 TEST_IMG="$DRIVER,file.filename=$SOCK_DIR/fuse-t.$IMGFMT" 293 elif [ "$IMGPROTO" = "ssh" ]; then 294 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 295 TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE" 296 elif [ "$IMGPROTO" = "nfs" ]; then 297 TEST_DIR="$DRIVER,file.driver=nfs,file.filename=nfs://127.0.0.1/$TEST_DIR" 298 TEST_IMG=$TEST_DIR/t.$IMGFMT 299 else 300 TEST_IMG="$DRIVER,file.driver=$IMGPROTO,file.filename=$TEST_DIR/t.$IMGFMT" 301 fi 302else 303 QEMU_IMG_EXTRA_ARGS= 304 if [ "$IMGPROTO" = "file" ]; then 305 TEST_IMG=$TEST_DIR/t.$IMGFMT 306 elif [ "$IMGPROTO" = "nbd" ]; then 307 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 308 TEST_IMG="nbd+unix:///?socket=$SOCK_DIR/nbd" 309 elif [ "$IMGPROTO" = "fuse" ]; then 310 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 311 TEST_IMG="$SOCK_DIR/fuse-t.$IMGFMT" 312 elif [ "$IMGPROTO" = "ssh" ]; then 313 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 314 REMOTE_TEST_DIR="ssh://\\($USER@\\)\\?127.0.0.1\\(:[0-9]\\+\\)\\?$TEST_DIR" 315 TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" 316 elif [ "$IMGPROTO" = "nfs" ]; then 317 TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT 318 REMOTE_TEST_DIR="nfs://127.0.0.1$TEST_DIR" 319 TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" 320 else 321 TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT 322 fi 323fi 324ORIG_TEST_IMG_FILE=$TEST_IMG_FILE 325ORIG_TEST_IMG="$TEST_IMG" 326 327FUSE_PIDS=() 328FUSE_EXPORTS=() 329 330if [ -z "$TEST_DIR" ]; then 331 TEST_DIR=$PWD/scratch 332fi 333 334QEMU_TEST_DIR="${TEST_DIR}" 335 336if [ ! -e "$TEST_DIR" ]; then 337 mkdir "$TEST_DIR" 338fi 339 340if [ ! -d "$TEST_DIR" ]; then 341 echo "common.rc: Error: \$TEST_DIR ($TEST_DIR) is not a directory" 342 exit 1 343fi 344 345if [ -z "$REMOTE_TEST_DIR" ]; then 346 REMOTE_TEST_DIR="$TEST_DIR" 347fi 348 349if [ ! -d "$SAMPLE_IMG_DIR" ]; then 350 echo "common.rc: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory" 351 exit 1 352fi 353 354_use_sample_img() 355{ 356 SAMPLE_IMG_FILE="${1%\.bz2}" 357 TEST_IMG="$TEST_DIR/$SAMPLE_IMG_FILE" 358 bzcat "$SAMPLE_IMG_DIR/$1" > "$TEST_IMG" 359 if [ $? -ne 0 ] 360 then 361 echo "_use_sample_img error, cannot extract '$SAMPLE_IMG_DIR/$1'" 362 exit 1 363 fi 364} 365 366_stop_nbd_server() 367{ 368 if [ -f "${QEMU_TEST_DIR}/qemu-nbd.pid" ]; then 369 local QEMU_NBD_PID 370 read QEMU_NBD_PID < "${QEMU_TEST_DIR}/qemu-nbd.pid" 371 kill ${QEMU_NBD_PID} 372 rm -f "${QEMU_TEST_DIR}/qemu-nbd.pid" "$SOCK_DIR/nbd" 373 fi 374} 375 376# Gets the data_file value from IMGOPTS and replaces the '$TEST_IMG' 377# pattern by '$1' 378# Caution: The replacement is done with sed, so $1 must be escaped 379# properly. (The delimiter is '#'.) 380_get_data_file() 381{ 382 if ! echo "$IMGOPTS" | grep -q 'data_file='; then 383 return 1 384 fi 385 386 echo "$IMGOPTS" | sed -e 's/.*data_file=\([^,]*\).*/\1/' \ 387 | sed -e "s#\\\$TEST_IMG#$1#" 388} 389 390# Translate a $TEST_IMG to its corresponding $TEST_IMG_FILE for 391# different protocols 392_test_img_to_test_img_file() 393{ 394 case "$IMGPROTO" in 395 file) 396 echo "$1" 397 ;; 398 399 fuse) 400 echo "$1" | sed -e "s#$SOCK_DIR/fuse-#$TEST_DIR/#" 401 ;; 402 403 nfs) 404 echo "$1" | sed -e "s#nfs://127.0.0.1##" 405 ;; 406 407 ssh) 408 echo "$1" | \ 409 sed -e "s#ssh://\\($USER@\\)\\?127.0.0.1\\(:[0-9]\\+\\)\\?##" 410 ;; 411 412 *) 413 return 1 414 ;; 415 esac 416} 417 418_make_test_img() 419{ 420 # extra qemu-img options can be added by tests 421 # at least one argument (the image size) needs to be added 422 local extra_img_options="" 423 local optstr="" 424 local img_name="" 425 local use_backing=0 426 local backing_file="" 427 local object_options="" 428 local opts_param=false 429 local misc_params=() 430 431 if [[ $IMGPROTO == fuse && $TEST_IMG == $SOCK_DIR/fuse-* ]]; then 432 # The caller may be trying to overwrite an existing image 433 _rm_test_img "$TEST_IMG" 434 fi 435 436 if [ -z "$TEST_IMG_FILE" ]; then 437 img_name=$TEST_IMG 438 elif [ "$IMGOPTSSYNTAX" != "true" -a \ 439 "$TEST_IMG_FILE" = "$ORIG_TEST_IMG_FILE" ]; then 440 # Handle cases of tests only updating TEST_IMG, but not TEST_IMG_FILE 441 img_name=$(_test_img_to_test_img_file "$TEST_IMG") 442 if [ "$?" != 0 ]; then 443 img_name=$TEST_IMG_FILE 444 fi 445 else 446 # $TEST_IMG_FILE is not the default value, so it definitely has been 447 # modified by the test 448 img_name=$TEST_IMG_FILE 449 fi 450 451 if [ -n "$IMGOPTS" ]; then 452 imgopts_expanded=$(echo "$IMGOPTS" | sed -e "s#\\\$TEST_IMG#$img_name#") 453 optstr=$(_optstr_add "$optstr" "$imgopts_expanded") 454 fi 455 if [ -n "$IMGKEYSECRET" ]; then 456 object_options="--object secret,id=keysec0,data=$IMGKEYSECRET" 457 optstr=$(_optstr_add "$optstr" "key-secret=keysec0") 458 fi 459 460 for param; do 461 if [ "$use_backing" = "1" -a -z "$backing_file" ]; then 462 backing_file=$param 463 continue 464 elif $opts_param; then 465 optstr=$(_optstr_add "$optstr" "$param") 466 opts_param=false 467 continue 468 fi 469 470 case "$param" in 471 -b) 472 use_backing=1 473 ;; 474 475 -o) 476 opts_param=true 477 ;; 478 479 --no-opts) 480 optstr="" 481 ;; 482 483 *) 484 misc_params=("${misc_params[@]}" "$param") 485 ;; 486 esac 487 done 488 489 if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then 490 optstr=$(_optstr_add "$optstr" "cluster_size=$CLUSTER_SIZE") 491 fi 492 493 if [ -n "$optstr" ]; then 494 extra_img_options="-o $optstr $extra_img_options" 495 fi 496 497 if [ $IMGPROTO = "nbd" ]; then 498 _stop_nbd_server 499 fi 500 501 # XXX(hch): have global image options? 502 ( 503 if [ $use_backing = 1 ]; then 504 $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" "${misc_params[@]}" 2>&1 505 else 506 $QEMU_IMG create $object_options -f $IMGFMT $extra_img_options "$img_name" "${misc_params[@]}" 2>&1 507 fi 508 ) | _filter_img_create 509 510 # Start an NBD server on the image file, which is what we'll be talking to. 511 # Once NBD gains resize support, we may also want to use -f raw at the 512 # server and interpret format over NBD, but for now, the format is 513 # interpreted at the server and raw data sent over NBD. 514 if [ $IMGPROTO = "nbd" ]; then 515 # Pass a sufficiently high number to -e that should be enough for all 516 # tests 517 eval "$QEMU_NBD -v -t -k '$SOCK_DIR/nbd' -f $IMGFMT -e 42 -x '' $TEST_IMG_FILE >/dev/null &" 518 sleep 1 # FIXME: qemu-nbd needs to be listening before we continue 519 fi 520 521 if [ $IMGPROTO = "fuse" -a -f "$img_name" ]; then 522 local export_mp 523 local pid 524 local pidfile 525 local timeout 526 527 export_mp=$(echo "$img_name" | sed -e "s#$TEST_DIR/#$SOCK_DIR/fuse-#") 528 if ! echo "$export_mp" | grep -q "^$SOCK_DIR"; then 529 echo 'Cannot use FUSE exports with images outside of TEST_DIR' >&2 530 return 1 531 fi 532 533 touch "$export_mp" 534 rm -f "$SOCK_DIR/fuse-output" 535 536 # Usually, users would export formatted nodes. But we present fuse as a 537 # protocol-level driver here, so we have to leave the format to the 538 # client. 539 # Switch off allow-other, because in general we do not need it for 540 # iotests. The default allow-other=auto has the downside of printing a 541 # fusermount error on its first attempt if allow_other is not 542 # permissible, which we would need to filter. 543 QSD_NEED_PID=y $QSD \ 544 --blockdev file,node-name=export-node,filename=$img_name,discard=unmap \ 545 --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=on,allow-other=off \ 546 & 547 548 pidfile="$QEMU_TEST_DIR/qemu-storage-daemon.pid" 549 550 # Wait for the PID file 551 while [ ! -f "$pidfile" ]; do 552 sleep 0.5 553 done 554 555 pid=$(cat "$pidfile") 556 rm -f "$pidfile" 557 558 FUSE_PIDS+=($pid) 559 FUSE_EXPORTS+=("$export_mp") 560 fi 561} 562 563_rm_test_img() 564{ 565 local img=$1 566 567 if [[ $IMGPROTO == fuse && $img == $SOCK_DIR/fuse-* ]]; then 568 # Drop a FUSE export 569 local df_output 570 local i 571 local image_file 572 local index='' 573 local timeout 574 575 for i in "${!FUSE_EXPORTS[@]}"; do 576 if [ "${FUSE_EXPORTS[i]}" = "$img" ]; then 577 index=$i 578 break 579 fi 580 done 581 582 if [ -z "$index" ]; then 583 # Probably gone already 584 return 0 585 fi 586 587 kill "${FUSE_PIDS[index]}" 588 589 # Wait until the mount is gone 590 timeout=10 # *0.5 s 591 while true; do 592 # Will show the mount point; if the mount is still there, 593 # it will be $img. 594 df_output=$(df "$img" 2>/dev/null) 595 596 # But df may also show an error ("Transpoint endpoint not 597 # connected"), so retry in such cases 598 if [ -n "$df_output" ]; then 599 if ! echo "$df_output" | grep -q "$img"; then 600 break 601 fi 602 fi 603 604 sleep 0.5 605 606 timeout=$((timeout - 1)) 607 if [ "$timeout" = 0 ]; then 608 echo 'Failed to take down FUSE export' >&2 609 return 1 610 fi 611 done 612 613 rm -f "$img" 614 615 unset "FUSE_PIDS[$index]" 616 unset "FUSE_EXPORTS[$index]" 617 618 image_file=$(echo "$img" | sed -e "s#$SOCK_DIR/fuse-#$TEST_DIR/#") 619 _rm_test_img "$image_file" 620 return 621 fi 622 623 if [ "$IMGFMT" = "vmdk" ]; then 624 # Remove all the extents for vmdk 625 "$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \ 626 | xargs -I {} rm -f "{}" 627 elif [ "$IMGFMT" = "qcow2" ]; then 628 # Remove external data file 629 if data_file=$(_get_data_file "$img"); then 630 rm -f "$data_file" 631 fi 632 fi 633 rm -f "$img" 634} 635 636_cleanup_test_img() 637{ 638 case "$IMGPROTO" in 639 640 nbd) 641 _stop_nbd_server 642 rm -f "$TEST_IMG_FILE" 643 ;; 644 645 fuse) 646 local mp 647 648 for mp in "${FUSE_EXPORTS[@]}"; do 649 _rm_test_img "$mp" 650 done 651 652 FUSE_PIDS=() 653 FUSE_EXPORTS=() 654 ;; 655 656 file) 657 _rm_test_img "$TEST_DIR/t.$IMGFMT" 658 _rm_test_img "$TEST_DIR/t.$IMGFMT.orig" 659 _rm_test_img "$TEST_DIR/t.$IMGFMT.base" 660 if [ -n "$SAMPLE_IMG_FILE" ] 661 then 662 rm -f "$TEST_DIR/$SAMPLE_IMG_FILE" 663 SAMPLE_IMG_FILE= 664 TEST_IMG="$ORIG_TEST_IMG" 665 fi 666 ;; 667 668 rbd) 669 rbd --no-progress rm "$TEST_DIR/t.$IMGFMT" > /dev/null 670 ;; 671 672 esac 673} 674 675_check_test_img() 676{ 677 ( 678 if [ "$IMGOPTSSYNTAX" = "true" ]; then 679 $QEMU_IMG check $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 680 else 681 $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 682 fi 683 ) | _filter_testdir | _filter_qemu_img_check 684 685 # return real qemu_img check status, to analyze in 686 # _check_test_img_ignore_leaks 687 return ${PIPESTATUS[0]} 688} 689 690_check_test_img_ignore_leaks() 691{ 692 out=$(_check_test_img "$@") 693 status=$? 694 if [ $status = 3 ]; then 695 # This must correspond to success output in dump_human_image_check() 696 echo "No errors were found on the image." 697 return 0 698 fi 699 echo "$out" 700 return $status 701} 702 703_img_info() 704{ 705 if [[ "$1" == "--format-specific" ]]; then 706 local format_specific=1 707 shift 708 else 709 local format_specific=0 710 fi 711 712 discard=0 713 regex_json_spec_start='^ *"format-specific": \{' 714 regex_json_child_start='^ *"children": \[' 715 $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ 716 sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ 717 -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ 718 -e "s#$TEST_DIR#TEST_DIR#g" \ 719 -e "s#$SOCK_DIR/fuse-#TEST_DIR/#g" \ 720 -e "s#$SOCK_DIR/#SOCK_DIR/#g" \ 721 -e "s#$IMGFMT#IMGFMT#g" \ 722 -e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \ 723 -e "/^disk size:/ D" \ 724 -e "/actual-size/ D" | \ 725 while IFS='' read -r line; do 726 if [[ $discard == 0 ]]; then 727 if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then 728 discard=1 729 elif [[ $line =~ "Child node '/" ]]; then 730 discard=1 731 elif [[ $format_specific == 0 && $line =~ $regex_json_spec_start ]]; then 732 discard=2 733 regex_json_end="^${line%%[^ ]*}\\},? *$" 734 elif [[ $line =~ $regex_json_child_start ]]; then 735 discard=2 736 regex_json_end="^${line%%[^ ]*}\\],? *$" 737 fi 738 fi 739 if [[ $discard == 0 ]]; then 740 echo "$line" 741 elif [[ $discard == 1 && ! $line ]]; then 742 echo 743 discard=0 744 elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then 745 discard=0 746 fi 747 done 748} 749 750# bail out, setting up .casenotrun file 751# The function _casenotrun() is used as a notifier. It is the 752# caller's responsibility to make skipped a particular test. 753# 754_casenotrun() 755{ 756 echo " [case not run] $*" >>"$TEST_DIR/$seq.casenotrun" 757} 758 759# just plain bail out 760# 761_fail() 762{ 763 echo "$*" | tee -a "$TEST_DIR/$seq.full" 764 echo "(see $seq.full for details)" 765 status=1 766 exit 1 767} 768 769# tests whether $IMGFMT is one of the supported image formats for a test 770# 771_supported_fmt() 772{ 773 # "generic" is suitable for most image formats. For some formats it doesn't 774 # work, however (most notably read-only formats), so they can opt out by 775 # setting IMGFMT_GENERIC to false. 776 for f; do 777 if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then 778 if [ "$IMGFMT" = "luks" ]; then 779 _require_working_luks 780 fi 781 return 782 fi 783 done 784 785 _notrun "not suitable for this image format: $IMGFMT" 786} 787 788# tests whether $IMGFMT is one of the unsupported image format for a test 789# 790_unsupported_fmt() 791{ 792 for f; do 793 if [ "$f" = "$IMGFMT" ]; then 794 _notrun "not suitable for this image format: $IMGFMT" 795 fi 796 done 797} 798 799# tests whether $IMGPROTO is one of the supported image protocols for a test 800# 801_supported_proto() 802{ 803 for f; do 804 if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then 805 return 806 fi 807 done 808 809 _notrun "not suitable for this image protocol: $IMGPROTO" 810} 811 812# tests whether $IMGPROTO is specified as an unsupported image protocol for a test 813# 814_unsupported_proto() 815{ 816 for f; do 817 if [ "$f" = "$IMGPROTO" ]; then 818 _notrun "not suitable for this image protocol: $IMGPROTO" 819 return 820 fi 821 done 822} 823 824# tests whether the host OS is one of the supported OSes for a test 825# 826_supported_os() 827{ 828 for h 829 do 830 if [ "$h" = "$HOSTOS" ] 831 then 832 return 833 fi 834 done 835 836 _notrun "not suitable for this OS: $HOSTOS" 837} 838 839_supported_cache_modes() 840{ 841 for mode; do 842 if [ "$mode" = "$CACHEMODE" ]; then 843 return 844 fi 845 done 846 _notrun "not suitable for cache mode: $CACHEMODE" 847} 848 849# Check whether the filesystem supports O_DIRECT 850_check_o_direct() 851{ 852 testfile="$TEST_DIR"/_check_o_direct 853 $QEMU_IMG create -f raw "$testfile" 1M > /dev/null 854 out=$($QEMU_IO -f raw -t none -c quit "$testfile" 2>&1) 855 rm -f "$testfile" 856 857 [[ "$out" != *"O_DIRECT"* ]] 858} 859 860_require_o_direct() 861{ 862 if ! _check_o_direct; then 863 _notrun "file system on $TEST_DIR does not support O_DIRECT" 864 fi 865} 866 867_check_cache_mode() 868{ 869 if [ $CACHEMODE == "none" ] || [ $CACHEMODE == "directsync" ]; then 870 _require_o_direct 871 fi 872} 873 874_check_cache_mode 875 876# $1 - cache mode to use by default 877# $2 - (optional) cache mode to use by default if O_DIRECT is not supported 878_default_cache_mode() 879{ 880 if $CACHEMODE_IS_DEFAULT; then 881 if [ -z "$2" ] || _check_o_direct; then 882 CACHEMODE="$1" 883 else 884 CACHEMODE="$2" 885 fi 886 QEMU_IO="$QEMU_IO --cache $CACHEMODE" 887 _check_cache_mode 888 return 889 fi 890} 891_supported_aio_modes() 892{ 893 for mode; do 894 if [ "$mode" = "$AIOMODE" ]; then 895 return 896 fi 897 done 898 _notrun "not suitable for aio mode: $AIOMODE" 899} 900_default_aio_mode() 901{ 902 AIOMODE="$1" 903 QEMU_IO="$QEMU_IO --aio $1" 904} 905 906_unsupported_imgopts() 907{ 908 for bad_opt 909 do 910 # Add a space so tests can match for whitespace that marks the 911 # end of an option (\b or \> are not portable) 912 if echo "$IMGOPTS " | grep -q 2>/dev/null "$bad_opt" 913 then 914 _notrun "not suitable for image option: $bad_opt" 915 fi 916 done 917} 918 919# Caution: Overwrites $TEST_DIR/t.luks 920_require_working_luks() 921{ 922 file="$TEST_DIR/t.luks" 923 924 output=$( 925 $QEMU_IMG create -f luks \ 926 --object secret,id=sec0,data=hunter0 \ 927 -o key-secret=sec0 \ 928 -o iter-time=10 \ 929 "$file" \ 930 1M \ 931 2>&1 932 ) 933 status=$? 934 935 IMGFMT='luks' _rm_test_img "$file" 936 937 if [ $status != 0 ]; then 938 reason=$(echo "$output" | grep "$file:" | sed -e "s#.*$file: *##") 939 if [ -z "$reason" ]; then 940 reason="Failed to create a LUKS image" 941 fi 942 _notrun "$reason" 943 fi 944} 945 946# this test requires that a specified command (executable) exists 947# 948_require_command() 949{ 950 if [ "$1" = "QEMU" ]; then 951 c=$QEMU_PROG 952 elif [ "$1" = "QEMU_IMG" ]; then 953 c=$QEMU_IMG_PROG 954 elif [ "$1" = "QEMU_IO" ]; then 955 c=$QEMU_IO_PROG 956 elif [ "$1" = "QEMU_NBD" ]; then 957 c=$QEMU_NBD_PROG 958 else 959 eval c=\$$1 960 fi 961 [ -x "$c" ] || _notrun "$1 utility required, skipped this test" 962} 963 964# Check that a set of drivers has been whitelisted in the QEMU binary 965# 966_require_drivers() 967{ 968 available=$($QEMU -drive format=help | \ 969 sed -e '/Supported formats:/!d' -e 's/Supported formats://') 970 for driver 971 do 972 if ! echo "$available" | grep -q " $driver\( \|$\)"; then 973 _notrun "$driver not available" 974 fi 975 done 976} 977 978# Check that we have a file system that allows huge (but very sparse) files 979# 980_require_large_file() 981{ 982 if ! truncate --size="$1" "$TEST_IMG"; then 983 _notrun "file system on $TEST_DIR does not support large enough files" 984 fi 985 rm "$TEST_IMG" 986} 987 988# Check that a set of devices is available in the QEMU binary 989# 990_require_devices() 991{ 992 available=$($QEMU -M none -device help 2> /dev/null | \ 993 grep ^name | sed -e 's/^name "//' -e 's/".*$//') 994 for device 995 do 996 if ! echo "$available" | grep -q "$device" ; then 997 _notrun "$device not available" 998 fi 999 done 1000} 1001 1002_require_one_device_of() 1003{ 1004 available=$($QEMU -M none -device help 2> /dev/null | \ 1005 grep ^name | sed -e 's/^name "//' -e 's/".*$//') 1006 for device 1007 do 1008 if echo "$available" | grep -q "$device" ; then 1009 return 1010 fi 1011 done 1012 _notrun "$* not available" 1013} 1014 1015_qcow2_dump_header() 1016{ 1017 if [[ "$1" == "--no-filter-compression" ]]; then 1018 local filter_compression=0 1019 shift 1020 else 1021 local filter_compression=1 1022 fi 1023 1024 img="$1" 1025 if [ -z "$img" ]; then 1026 img="$TEST_IMG" 1027 fi 1028 1029 if [[ $filter_compression == 0 ]]; then 1030 $PYTHON qcow2.py "$img" dump-header 1031 else 1032 $PYTHON qcow2.py "$img" dump-header | _filter_qcow2_compression_type_bit 1033 fi 1034} 1035 1036# make sure this script returns success 1037true 1038