qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

common.rc (27262B)


      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 
     20 export LANG=C
     21 
     22 PATH=".:$PATH"
     23 
     24 HOSTOS=$(uname -s)
     25 arch=$(uname -m)
     26 [[ "$arch" =~ "ppc64" ]] && qemu_arch=ppc64 || qemu_arch="$arch"
     27 
     28 # make sure we have a standard umask
     29 umask 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 
     40 if ! 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
     53 fi
     54 
     55 dd()
     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'
     73 poke_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
     80 poke_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
     94 poke_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
    103 peek_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
    116 peek_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.
    129 peek_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 
    268 export QEMU=_qemu_wrapper
    269 export QEMU_IMG=_qemu_img_wrapper
    270 export QEMU_IO=_qemu_io_wrapper
    271 export QEMU_NBD=_qemu_nbd_wrapper
    272 export QSD=_qemu_storage_daemon_wrapper
    273 
    274 if [ "$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
    302 else
    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
    323 fi
    324 ORIG_TEST_IMG_FILE=$TEST_IMG_FILE
    325 ORIG_TEST_IMG="$TEST_IMG"
    326 
    327 FUSE_PIDS=()
    328 FUSE_EXPORTS=()
    329 
    330 if [ -z "$TEST_DIR" ]; then
    331         TEST_DIR=$PWD/scratch
    332 fi
    333 
    334 QEMU_TEST_DIR="${TEST_DIR}"
    335 
    336 if [ ! -e "$TEST_DIR" ]; then
    337         mkdir "$TEST_DIR"
    338 fi
    339 
    340 if [ ! -d "$TEST_DIR" ]; then
    341     echo "common.rc: Error: \$TEST_DIR ($TEST_DIR) is not a directory"
    342     exit 1
    343 fi
    344 
    345 if [ -z "$REMOTE_TEST_DIR" ]; then
    346     REMOTE_TEST_DIR="$TEST_DIR"
    347 fi
    348 
    349 if [ ! -d "$SAMPLE_IMG_DIR" ]; then
    350     echo "common.rc: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory"
    351     exit 1
    352 fi
    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 2> /dev/null | \
    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 2> /dev/null | \
    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
   1030 true