1#!/usr/bin/env bash 2# 3# Copyright (C) 2009 Red Hat, Inc. 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 $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ 715 sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ 716 -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ 717 -e "s#$TEST_DIR#TEST_DIR#g" \ 718 -e "s#$SOCK_DIR/fuse-#TEST_DIR/#g" \ 719 -e "s#$IMGFMT#IMGFMT#g" \ 720 -e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \ 721 -e "/^disk size:/ D" \ 722 -e "/actual-size/ D" | \ 723 while IFS='' read -r line; do 724 if [[ $format_specific == 1 ]]; then 725 discard=0 726 elif [[ $line == "Format specific information:" ]]; then 727 discard=1 728 elif [[ $line =~ $regex_json_spec_start ]]; then 729 discard=2 730 regex_json_spec_end="^${line%%[^ ]*}\\},? *$" 731 fi 732 if [[ $discard == 0 ]]; then 733 echo "$line" 734 elif [[ $discard == 1 && ! $line ]]; then 735 echo 736 discard=0 737 elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then 738 discard=0 739 fi 740 done 741} 742 743# bail out, setting up .casenotrun file 744# The function _casenotrun() is used as a notifier. It is the 745# caller's responsibility to make skipped a particular test. 746# 747_casenotrun() 748{ 749 echo " [case not run] $*" >>"$TEST_DIR/$seq.casenotrun" 750} 751 752# just plain bail out 753# 754_fail() 755{ 756 echo "$*" | tee -a "$TEST_DIR/$seq.full" 757 echo "(see $seq.full for details)" 758 status=1 759 exit 1 760} 761 762# tests whether $IMGFMT is one of the supported image formats for a test 763# 764_supported_fmt() 765{ 766 # "generic" is suitable for most image formats. For some formats it doesn't 767 # work, however (most notably read-only formats), so they can opt out by 768 # setting IMGFMT_GENERIC to false. 769 for f; do 770 if [ "$f" = "$IMGFMT" -o "$f" = "generic" -a "$IMGFMT_GENERIC" = "true" ]; then 771 if [ "$IMGFMT" = "luks" ]; then 772 _require_working_luks 773 fi 774 return 775 fi 776 done 777 778 _notrun "not suitable for this image format: $IMGFMT" 779} 780 781# tests whether $IMGFMT is one of the unsupported image format for a test 782# 783_unsupported_fmt() 784{ 785 for f; do 786 if [ "$f" = "$IMGFMT" ]; then 787 _notrun "not suitable for this image format: $IMGFMT" 788 fi 789 done 790} 791 792# tests whether $IMGPROTO is one of the supported image protocols for a test 793# 794_supported_proto() 795{ 796 for f; do 797 if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then 798 return 799 fi 800 done 801 802 _notrun "not suitable for this image protocol: $IMGPROTO" 803} 804 805# tests whether $IMGPROTO is specified as an unsupported image protocol for a test 806# 807_unsupported_proto() 808{ 809 for f; do 810 if [ "$f" = "$IMGPROTO" ]; then 811 _notrun "not suitable for this image protocol: $IMGPROTO" 812 return 813 fi 814 done 815} 816 817# tests whether the host OS is one of the supported OSes for a test 818# 819_supported_os() 820{ 821 for h 822 do 823 if [ "$h" = "$HOSTOS" ] 824 then 825 return 826 fi 827 done 828 829 _notrun "not suitable for this OS: $HOSTOS" 830} 831 832_supported_cache_modes() 833{ 834 for mode; do 835 if [ "$mode" = "$CACHEMODE" ]; then 836 return 837 fi 838 done 839 _notrun "not suitable for cache mode: $CACHEMODE" 840} 841 842# Check whether the filesystem supports O_DIRECT 843_check_o_direct() 844{ 845 testfile="$TEST_DIR"/_check_o_direct 846 $QEMU_IMG create -f raw "$testfile" 1M > /dev/null 847 out=$($QEMU_IO -f raw -t none -c quit "$testfile" 2>&1) 848 rm -f "$testfile" 849 850 [[ "$out" != *"O_DIRECT"* ]] 851} 852 853_require_o_direct() 854{ 855 if ! _check_o_direct; then 856 _notrun "file system on $TEST_DIR does not support O_DIRECT" 857 fi 858} 859 860_check_cache_mode() 861{ 862 if [ $CACHEMODE == "none" ] || [ $CACHEMODE == "directsync" ]; then 863 _require_o_direct 864 fi 865} 866 867_check_cache_mode 868 869# $1 - cache mode to use by default 870# $2 - (optional) cache mode to use by default if O_DIRECT is not supported 871_default_cache_mode() 872{ 873 if $CACHEMODE_IS_DEFAULT; then 874 if [ -z "$2" ] || _check_o_direct; then 875 CACHEMODE="$1" 876 else 877 CACHEMODE="$2" 878 fi 879 QEMU_IO="$QEMU_IO --cache $CACHEMODE" 880 _check_cache_mode 881 return 882 fi 883} 884_supported_aio_modes() 885{ 886 for mode; do 887 if [ "$mode" = "$AIOMODE" ]; then 888 return 889 fi 890 done 891 _notrun "not suitable for aio mode: $AIOMODE" 892} 893_default_aio_mode() 894{ 895 AIOMODE="$1" 896 QEMU_IO="$QEMU_IO --aio $1" 897} 898 899_unsupported_imgopts() 900{ 901 for bad_opt 902 do 903 # Add a space so tests can match for whitespace that marks the 904 # end of an option (\b or \> are not portable) 905 if echo "$IMGOPTS " | grep -q 2>/dev/null "$bad_opt" 906 then 907 _notrun "not suitable for image option: $bad_opt" 908 fi 909 done 910} 911 912# Caution: Overwrites $TEST_DIR/t.luks 913_require_working_luks() 914{ 915 file="$TEST_DIR/t.luks" 916 917 output=$( 918 $QEMU_IMG create -f luks \ 919 --object secret,id=sec0,data=hunter0 \ 920 -o key-secret=sec0 \ 921 -o iter-time=10 \ 922 "$file" \ 923 1M \ 924 2>&1 925 ) 926 status=$? 927 928 IMGFMT='luks' _rm_test_img "$file" 929 930 if [ $status != 0 ]; then 931 reason=$(echo "$output" | grep "$file:" | sed -e "s#.*$file: *##") 932 if [ -z "$reason" ]; then 933 reason="Failed to create a LUKS image" 934 fi 935 _notrun "$reason" 936 fi 937} 938 939# this test requires that a specified command (executable) exists 940# 941_require_command() 942{ 943 if [ "$1" = "QEMU" ]; then 944 c=$QEMU_PROG 945 elif [ "$1" = "QEMU_IMG" ]; then 946 c=$QEMU_IMG_PROG 947 elif [ "$1" = "QEMU_IO" ]; then 948 c=$QEMU_IO_PROG 949 elif [ "$1" = "QEMU_NBD" ]; then 950 c=$QEMU_NBD_PROG 951 else 952 eval c=\$$1 953 fi 954 [ -x "$c" ] || _notrun "$1 utility required, skipped this test" 955} 956 957# Check that a set of drivers has been whitelisted in the QEMU binary 958# 959_require_drivers() 960{ 961 available=$($QEMU -drive format=help | \ 962 sed -e '/Supported formats:/!d' -e 's/Supported formats://') 963 for driver 964 do 965 if ! echo "$available" | grep -q " $driver\( \|$\)"; then 966 _notrun "$driver not available" 967 fi 968 done 969} 970 971# Check that we have a file system that allows huge (but very sparse) files 972# 973_require_large_file() 974{ 975 if ! truncate --size="$1" "$TEST_IMG"; then 976 _notrun "file system on $TEST_DIR does not support large enough files" 977 fi 978 rm "$TEST_IMG" 979} 980 981# Check that a set of devices is available in the QEMU binary 982# 983_require_devices() 984{ 985 available=$($QEMU -M none -device help | \ 986 grep ^name | sed -e 's/^name "//' -e 's/".*$//') 987 for device 988 do 989 if ! echo "$available" | grep -q "$device" ; then 990 _notrun "$device not available" 991 fi 992 done 993} 994 995_require_one_device_of() 996{ 997 available=$($QEMU -M none -device help | \ 998 grep ^name | sed -e 's/^name "//' -e 's/".*$//') 999 for device 1000 do 1001 if echo "$available" | grep -q "$device" ; then 1002 return 1003 fi 1004 done 1005 _notrun "$* not available" 1006} 1007 1008_qcow2_dump_header() 1009{ 1010 if [[ "$1" == "--no-filter-compression" ]]; then 1011 local filter_compression=0 1012 shift 1013 else 1014 local filter_compression=1 1015 fi 1016 1017 img="$1" 1018 if [ -z "$img" ]; then 1019 img="$TEST_IMG" 1020 fi 1021 1022 if [[ $filter_compression == 0 ]]; then 1023 $PYTHON qcow2.py "$img" dump-header 1024 else 1025 $PYTHON qcow2.py "$img" dump-header | _filter_qcow2_compression_type_bit 1026 fi 1027} 1028 1029# make sure this script returns success 1030true 1031