1#!/usr/bin/env bash 2 3rpc_py=rpc_cmd 4 5function xtrace_fd() { 6 if [[ -n $BASH_XTRACEFD && -e /proc/self/fd/$BASH_XTRACEFD ]]; then 7 # Close it first to make sure it's sane 8 exec {BASH_XTRACEFD}>&- 9 fi 10 exec {BASH_XTRACEFD}>&2 11 12 set -x 13} 14 15function xtrace_disable() { 16 if [ "$XTRACE_DISABLED" != "yes" ]; then 17 PREV_BASH_OPTS="$-" 18 if [[ "$PREV_BASH_OPTS" == *"x"* ]]; then 19 XTRACE_DISABLED="yes" 20 fi 21 set +x 22 elif [ -z $XTRACE_NESTING_LEVEL ]; then 23 XTRACE_NESTING_LEVEL=1 24 else 25 XTRACE_NESTING_LEVEL=$((++XTRACE_NESTING_LEVEL)) 26 fi 27} 28 29xtrace_disable 30set -e 31shopt -s expand_aliases 32 33if [[ -e $rootdir/test/common/build_config.sh ]]; then 34 source "$rootdir/test/common/build_config.sh" 35elif [[ -e $rootdir/mk/config.mk ]]; then 36 build_config=$(< "$rootdir/mk/config.mk") 37 source <(echo "${build_config//\?=/=}") 38else 39 source "$rootdir/CONFIG" 40fi 41 42# Source scripts after the config so that the definitions are available. 43source "$rootdir/test/common/applications.sh" 44source "$rootdir/scripts/common.sh" 45 46# Dummy function to be called after restoring xtrace just so that it appears in the 47# xtrace log. This way we can consistently track when xtrace is enabled/disabled. 48function xtrace_enable() { 49 # We have to do something inside a function in bash, and calling any command 50 # (even `:`) will produce an xtrace entry, so we just define another function. 51 function xtrace_dummy() { :; } 52} 53 54# Keep it as alias to avoid xtrace_enable backtrace always pointing to xtrace_restore. 55# xtrace_enable will appear as called directly from the user script, from the same line 56# that "called" xtrace_restore. 57alias xtrace_restore='if [ -z $XTRACE_NESTING_LEVEL ]; then 58 if [[ "$PREV_BASH_OPTS" == *"x"* ]]; then 59 XTRACE_DISABLED="no"; PREV_BASH_OPTS=""; set -x; xtrace_enable; 60 fi 61else 62 XTRACE_NESTING_LEVEL=$((--XTRACE_NESTING_LEVEL)); 63 if [ $XTRACE_NESTING_LEVEL -eq "0" ]; then 64 unset XTRACE_NESTING_LEVEL 65 fi 66fi' 67 68: ${RUN_NIGHTLY:=0} 69export RUN_NIGHTLY 70 71# Set defaults for missing test config options 72: ${SPDK_AUTOTEST_DEBUG_APPS:=0} 73export SPDK_AUTOTEST_DEBUG_APPS 74: ${SPDK_RUN_VALGRIND=0} 75export SPDK_RUN_VALGRIND 76: ${SPDK_RUN_FUNCTIONAL_TEST=0} 77export SPDK_RUN_FUNCTIONAL_TEST 78: ${SPDK_TEST_UNITTEST=0} 79export SPDK_TEST_UNITTEST 80: ${SPDK_TEST_AUTOBUILD=0} 81export SPDK_TEST_AUTOBUILD 82: ${SPDK_TEST_RELEASE_BUILD=0} 83export SPDK_TEST_RELEASE_BUILD 84: ${SPDK_TEST_ISAL=0} 85export SPDK_TEST_ISAL 86: ${SPDK_TEST_ISCSI=0} 87export SPDK_TEST_ISCSI 88: ${SPDK_TEST_ISCSI_INITIATOR=0} 89export SPDK_TEST_ISCSI_INITIATOR 90: ${SPDK_TEST_NVME=0} 91export SPDK_TEST_NVME 92: ${SPDK_TEST_NVME_PMR=0} 93export SPDK_TEST_NVME_PMR 94: ${SPDK_TEST_NVME_SCC=0} 95export SPDK_TEST_NVME_SCC 96: ${SPDK_TEST_NVME_BP=0} 97export SPDK_TEST_NVME_BP 98: ${SPDK_TEST_NVME_CLI=0} 99export SPDK_TEST_NVME_CLI 100: ${SPDK_TEST_NVME_CUSE=0} 101export SPDK_TEST_NVME_CUSE 102: ${SPDK_TEST_NVMF=0} 103export SPDK_TEST_NVMF 104: ${SPDK_TEST_VFIOUSER=0} 105export SPDK_TEST_VFIOUSER 106: ${SPDK_TEST_VFIOUSER_QEMU=0} 107export SPDK_TEST_VFIOUSER_QEMU 108: ${SPDK_TEST_FUZZER=0} 109export SPDK_TEST_FUZZER 110: ${SPDK_TEST_FUZZER_SHORT=0} 111export SPDK_TEST_FUZZER_SHORT 112: ${SPDK_TEST_NVMF_TRANSPORT="rdma"} 113export SPDK_TEST_NVMF_TRANSPORT 114: ${SPDK_TEST_RBD=0} 115export SPDK_TEST_RBD 116: ${SPDK_TEST_VHOST=0} 117export SPDK_TEST_VHOST 118: ${SPDK_TEST_BLOCKDEV=0} 119export SPDK_TEST_BLOCKDEV 120: ${SPDK_TEST_IOAT=0} 121export SPDK_TEST_IOAT 122: ${SPDK_TEST_BLOBFS=0} 123export SPDK_TEST_BLOBFS 124: ${SPDK_TEST_VHOST_INIT=0} 125export SPDK_TEST_VHOST_INIT 126: ${SPDK_TEST_PMDK=0} 127export SPDK_TEST_PMDK 128: ${SPDK_TEST_LVOL=0} 129export SPDK_TEST_LVOL 130: ${SPDK_TEST_REDUCE=0} 131export SPDK_TEST_REDUCE 132: ${SPDK_RUN_ASAN=0} 133export SPDK_RUN_ASAN 134: ${SPDK_RUN_UBSAN=0} 135export SPDK_RUN_UBSAN 136: ${SPDK_RUN_EXTERNAL_DPDK=""} 137export SPDK_RUN_EXTERNAL_DPDK 138: ${SPDK_RUN_NON_ROOT=0} 139export SPDK_RUN_NON_ROOT 140: ${SPDK_TEST_CRYPTO=0} 141export SPDK_TEST_CRYPTO 142: ${SPDK_TEST_FTL=0} 143export SPDK_TEST_FTL 144: ${SPDK_TEST_OCF=0} 145export SPDK_TEST_OCF 146: ${SPDK_TEST_VMD=0} 147export SPDK_TEST_VMD 148: ${SPDK_TEST_OPAL=0} 149export SPDK_TEST_OPAL 150: ${SPDK_TEST_NATIVE_DPDK} 151export SPDK_TEST_NATIVE_DPDK 152: ${SPDK_AUTOTEST_X=true} 153export SPDK_AUTOTEST_X 154: ${SPDK_TEST_RAID5=0} 155export SPDK_TEST_RAID5 156: ${SPDK_TEST_URING=0} 157export SPDK_TEST_URING 158: ${SPDK_TEST_USDT=0} 159export SPDK_TEST_USDT 160: ${SPDK_TEST_USE_IGB_UIO:=0} 161export SPDK_TEST_USE_IGB_UIO 162: ${SPDK_TEST_SCHEDULER:=0} 163export SPDK_TEST_SCHEDULER 164: ${SPDK_TEST_SCANBUILD:=0} 165export SPDK_TEST_SCANBUILD 166: ${SPDK_TEST_NVMF_NICS:=} 167export SPDK_TEST_NVMF_NICS 168: ${SPDK_TEST_SMA=0} 169export SPDK_TEST_SMA 170: ${SPDK_TEST_DAOS=0} 171export SPDK_TEST_DAOS 172: ${SPDK_TEST_XNVME:=0} 173export SPDK_TEST_XNVME 174 175# always test with SPDK shared objects. 176export SPDK_LIB_DIR="$rootdir/build/lib" 177export DPDK_LIB_DIR="${SPDK_RUN_EXTERNAL_DPDK:-$rootdir/dpdk/build}/lib" 178export VFIO_LIB_DIR="$rootdir/build/libvfio-user/usr/local/lib" 179export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SPDK_LIB_DIR:$DPDK_LIB_DIR:$VFIO_LIB_DIR 180 181# Tell setup.sh to wait for block devices upon each reset 182export PCI_BLOCK_SYNC_ON_RESET=yes 183 184# Export PYTHONPATH with addition of RPC framework. New scripts can be created 185# specific use cases for tests. 186export PYTHONPATH=$PYTHONPATH:$rootdir/python 187 188# Don't create Python .pyc files. When running with sudo these will be 189# created with root ownership and can cause problems when cleaning the repository. 190export PYTHONDONTWRITEBYTECODE=1 191 192# Export flag to skip the known bug that exists in librados 193# Bug is reported on ceph bug tracker with number 24078 194export ASAN_OPTIONS=new_delete_type_mismatch=0:disable_coredump=0 195export UBSAN_OPTIONS='halt_on_error=1:print_stacktrace=1:abort_on_error=1:disable_coredump=0' 196 197# Export LeakSanitizer option to use suppression file in order to prevent false positives 198# and known leaks in external executables or libraries from showing up. 199asan_suppression_file="/var/tmp/asan_suppression_file" 200rm -rf "$asan_suppression_file" 2> /dev/null || sudo rm -rf "$asan_suppression_file" 201cat << EOL >> "$asan_suppression_file" 202# ASAN has some bugs around thread_local variables. We have a destructor in place 203# to free the thread contexts, but ASAN complains about the leak before those 204# destructors have a chance to run. So suppress this one specific leak using 205# LSAN_OPTIONS. 206leak:spdk_fs_alloc_thread_ctx 207 208# Suppress known leaks in fio project 209leak:$CONFIG_FIO_SOURCE_DIR/parse.c 210leak:$CONFIG_FIO_SOURCE_DIR/iolog.c 211leak:$CONFIG_FIO_SOURCE_DIR/init.c 212leak:$CONFIG_FIO_SOURCE_DIR/filesetup.c 213leak:fio_memalign 214leak:spdk_fio_io_u_init 215# Suppress leaks in gperftools-libs from fio 216leak:libtcmalloc_minimal.so 217 218# Suppress leaks in libiscsi 219leak:libiscsi.so 220EOL 221 222# Suppress leaks in libfuse3 223echo "leak:libfuse3.so" >> "$asan_suppression_file" 224 225export LSAN_OPTIONS=suppressions="$asan_suppression_file" 226 227export DEFAULT_RPC_ADDR="/var/tmp/spdk.sock" 228 229if [ -z "$DEPENDENCY_DIR" ]; then 230 export DEPENDENCY_DIR=$HOME/spdk_dependencies 231else 232 export DEPENDENCY_DIR 233fi 234 235# Export location of where all the SPDK binaries are 236export SPDK_BIN_DIR="$rootdir/build/bin" 237export SPDK_EXAMPLE_DIR="$rootdir/build/examples" 238 239# for vhost, vfio-user tests 240export QEMU_BIN=${QEMU_BIN:-} 241export VFIO_QEMU_BIN=${VFIO_QEMU_BIN:-} 242 243export AR_TOOL=$rootdir/scripts/ar-xnvme-fixer 244 245# pass our valgrind desire on to unittest.sh 246if [ $SPDK_RUN_VALGRIND -eq 0 ]; then 247 export valgrind='' 248fi 249 250if [ "$(uname -s)" = "Linux" ]; then 251 HUGEMEM=${HUGEMEM:-4096} 252 export CLEAR_HUGE=yes 253 if [[ $SPDK_TEST_CRYPTO -eq 1 || $SPDK_TEST_REDUCE -eq 1 ]]; then 254 # Make sure that memory is distributed across all NUMA nodes - by default, all goes to 255 # node0, but if QAT devices are attached to a different node, all of their VFs will end 256 # up under that node too and memory needs to be available there for the tests. 257 export HUGE_EVEN_ALLOC=yes 258 fi 259 260 MAKE="make" 261 MAKEFLAGS=${MAKEFLAGS:--j$(nproc)} 262 if [[ $SPDK_TEST_USE_IGB_UIO -eq 1 ]]; then 263 export DRIVER_OVERRIDE=igb_uio 264 # Building kernel modules requires root privileges 265 MAKE="sudo $MAKE" 266 fi 267elif [ "$(uname -s)" = "FreeBSD" ]; then 268 MAKE="gmake" 269 MAKEFLAGS=${MAKEFLAGS:--j$(sysctl -a | grep -E -i 'hw.ncpu' | awk '{print $2}')} 270 # FreeBSD runs a much more limited set of tests, so keep the default 2GB. 271 HUGEMEM=${HUGEMEM:-2048} 272elif [ "$(uname -s)" = "Windows" ]; then 273 MAKE="make" 274 MAKEFLAGS=${MAKEFLAGS:--j$(nproc)} 275 # Keep the default 2GB for Windows. 276 HUGEMEM=${HUGEMEM:-2048} 277else 278 echo "Unknown OS \"$(uname -s)\"" 279 exit 1 280fi 281 282export HUGEMEM=$HUGEMEM 283 284if [ -z "$output_dir" ]; then 285 mkdir -p "$rootdir/../output" 286 export output_dir="$rootdir/../output" 287fi 288 289TEST_MODE= 290for i in "$@"; do 291 case "$i" in 292 --iso) 293 TEST_MODE=iso 294 ;; 295 --transport=*) 296 TEST_TRANSPORT="${i#*=}" 297 ;; 298 --sock=*) 299 TEST_SOCK="${i#*=}" 300 ;; 301 esac 302done 303 304# start rpc.py coprocess if it's not started yet 305if [[ -z $RPC_PIPE_PID ]] || ! kill -0 "$RPC_PIPE_PID" &> /dev/null; then 306 # Include list to all known plugins we use in the tests 307 PYTHONPATH+=":$rootdir/test/rpc_plugins" 308 coproc RPC_PIPE { PYTHONPATH="$PYTHONPATH" "$rootdir/scripts/rpc.py" --server; } 309 exec {RPC_PIPE_OUTPUT}<&${RPC_PIPE[0]} {RPC_PIPE_INPUT}>&${RPC_PIPE[1]} 310 # all descriptors will automatically close together with this bash 311 # process, this will make rpc.py stop reading and exit gracefully 312fi 313 314function set_test_storage() { 315 [[ -v testdir ]] || return 0 316 317 local requested_size=$1 # bytes 318 local mount target_dir 319 320 local -A mounts fss sizes avails uses 321 local source fs size avail mount use 322 323 local storage_fallback storage_candidates 324 325 storage_fallback=$(mktemp -udt spdk.XXXXXX) 326 storage_candidates=( 327 "$testdir" 328 "$storage_fallback/tests/${testdir##*/}" 329 "$storage_fallback" 330 ) 331 332 if [[ -n $ADD_TEST_STORAGE ]]; then 333 # List of dirs|mounts separated by whitespaces 334 storage_candidates+=($ADD_TEST_STORAGE) 335 fi 336 337 if [[ -n $DEDICATED_TEST_STORAGE ]]; then 338 # Single, dedicated dir|mount 339 storage_candidates=("$DEDICATED_TEST_STORAGE") 340 fi 341 342 mkdir -p "${storage_candidates[@]}" 343 344 # add some headroom - 64M 345 requested_size=$((requested_size + (64 << 20))) 346 347 while read -r source fs size use avail _ mount; do 348 mounts["$mount"]=$source fss["$mount"]=$fs 349 avails["$mount"]=$((avail * 1024)) sizes["$mount"]=$((size * 1024)) 350 uses["$mount"]=$((use * 1024)) 351 done < <(df -T | grep -v Filesystem) 352 353 printf '* Looking for test storage...\n' >&2 354 355 local target_space new_size 356 for target_dir in "${storage_candidates[@]}"; do 357 # FreeBSD's df is lacking the --output arg 358 # mount=$(df --output=target "$target_dir" | grep -v "Mounted on") 359 mount=$(df "$target_dir" | awk '$1 !~ /Filesystem/{print $6}') 360 361 target_space=${avails["$mount"]} 362 if ((target_space == 0 || target_space < requested_size)); then 363 continue 364 fi 365 if ((target_space >= requested_size)); then 366 # For in-memory fs, and / make sure our requested size won't fill most of the space. 367 if [[ ${fss["$mount"]} == tmpfs ]] || [[ ${fss["$mount"]} == ramfs ]] || [[ $mount == / ]]; then 368 new_size=$((uses["$mount"] + requested_size)) 369 if ((new_size * 100 / sizes["$mount"] > 95)); then 370 continue 371 fi 372 fi 373 fi 374 export SPDK_TEST_STORAGE=$target_dir 375 printf '* Found test storage at %s\n' "$SPDK_TEST_STORAGE" >&2 376 return 0 377 done 378 printf '* Test storage is not available\n' 379 return 1 380} 381 382function get_config_params() { 383 xtrace_disable 384 config_params='--enable-debug --enable-werror' 385 386 # for options with dependencies but no test flag, set them here 387 if [ -f /usr/include/infiniband/verbs.h ]; then 388 config_params+=' --with-rdma' 389 fi 390 391 if [ $SPDK_TEST_USDT -eq 1 ]; then 392 config_params+=" --with-usdt" 393 fi 394 395 if [ $(uname -s) == "FreeBSD" ]; then 396 intel="hw.model: Intel" 397 cpu_vendor=$(sysctl -a | grep hw.model | cut -c 1-15) 398 else 399 intel="GenuineIntel" 400 cpu_vendor=$(grep -i 'vendor' /proc/cpuinfo --max-count=1) 401 fi 402 if [[ "$cpu_vendor" != *"$intel"* ]]; then 403 config_params+=" --without-idxd" 404 else 405 config_params+=" --with-idxd" 406 fi 407 408 if [[ -d $CONFIG_FIO_SOURCE_DIR ]]; then 409 config_params+=" --with-fio=$CONFIG_FIO_SOURCE_DIR" 410 fi 411 412 if [ -d ${DEPENDENCY_DIR}/vtune_codes ]; then 413 config_params+=' --with-vtune='${DEPENDENCY_DIR}'/vtune_codes' 414 fi 415 416 if [ -d /usr/include/iscsi ]; then 417 [[ $(< /usr/include/iscsi/iscsi.h) =~ "define LIBISCSI_API_VERSION ("([0-9]+)")" ]] \ 418 && libiscsi_version=${BASH_REMATCH[1]} 419 if ((libiscsi_version >= 20150621)); then 420 config_params+=' --with-iscsi-initiator' 421 fi 422 fi 423 424 if [[ $SPDK_TEST_UNITTEST -eq 0 && \ 425 $SPDK_TEST_SCANBUILD -eq 0 && \ 426 $SPDK_TEST_AUTOBUILD -eq 0 ]]; then 427 config_params+=' --disable-unit-tests' 428 fi 429 430 if [ $SPDK_TEST_NVME_CUSE -eq 1 ]; then 431 config_params+=' --with-nvme-cuse' 432 fi 433 434 # for options with both dependencies and a test flag, set them here 435 if [ -f /usr/include/libpmemblk.h ] && [ $SPDK_TEST_PMDK -eq 1 ]; then 436 config_params+=' --with-pmdk' 437 fi 438 439 if [ -f /usr/include/libpmem.h ] && [ $SPDK_TEST_REDUCE -eq 1 ]; then 440 if ge "$(nasm --version | awk '{print $3}')" 2.14 && [[ $SPDK_TEST_ISAL -eq 1 ]]; then 441 config_params+=' --with-reduce' 442 fi 443 fi 444 445 if [ -d /usr/include/rbd ] && [ -d /usr/include/rados ] && [ $SPDK_TEST_RBD -eq 1 ]; then 446 config_params+=' --with-rbd' 447 fi 448 449 # for options with no required dependencies, just test flags, set them here 450 if [ $SPDK_TEST_CRYPTO -eq 1 ]; then 451 config_params+=' --with-crypto' 452 fi 453 454 if [ $SPDK_TEST_OCF -eq 1 ]; then 455 config_params+=" --with-ocf" 456 fi 457 458 if [ $SPDK_RUN_UBSAN -eq 1 ]; then 459 config_params+=' --enable-ubsan' 460 fi 461 462 if [ $SPDK_RUN_ASAN -eq 1 ]; then 463 config_params+=' --enable-asan' 464 fi 465 466 if [ "$(uname -s)" = "Linux" ]; then 467 config_params+=' --enable-coverage' 468 fi 469 470 if [ $SPDK_TEST_BLOBFS -eq 1 ]; then 471 if [[ -d /usr/include/fuse3 ]] || [[ -d /usr/local/include/fuse3 ]]; then 472 config_params+=' --with-fuse' 473 fi 474 fi 475 476 if [ $SPDK_TEST_RAID5 -eq 1 ]; then 477 config_params+=' --with-raid5f' 478 fi 479 480 if [ $SPDK_TEST_VFIOUSER -eq 1 ] || [ $SPDK_TEST_VFIOUSER_QEMU -eq 1 ]; then 481 config_params+=' --with-vfio-user' 482 fi 483 484 # Check whether liburing library header exists 485 if [ -f /usr/include/liburing/io_uring.h ] && [ $SPDK_TEST_URING -eq 1 ]; then 486 config_params+=' --with-uring' 487 fi 488 489 if [ -n "$SPDK_RUN_EXTERNAL_DPDK" ]; then 490 config_params+=" --with-dpdk=$SPDK_RUN_EXTERNAL_DPDK" 491 fi 492 493 if [[ $SPDK_TEST_SMA -eq 1 ]]; then 494 config_params+=' --with-sma' 495 config_params+=' --with-crypto' 496 fi 497 498 if [ -f /usr/include/daos.h ] && [ $SPDK_TEST_DAOS -eq 1 ]; then 499 config_params+=' --with-daos' 500 fi 501 502 # Make the xnvme module available for the tests 503 if [[ $SPDK_TEST_XNVME -eq 1 ]]; then 504 config_params+=' --with-xnvme' 505 fi 506 507 echo "$config_params" 508 xtrace_restore 509} 510 511function rpc_cmd() { 512 xtrace_disable 513 local rsp rc=1 514 local stdin cmd cmds_number=0 status_number=0 status 515 516 if (($#)); then 517 cmds_number=1 518 echo "$@" >&$RPC_PIPE_INPUT 519 elif [[ ! -t 0 ]]; then 520 mapfile -t stdin <&0 521 cmds_number=${#stdin[@]} 522 printf '%s\n' "${stdin[@]}" >&$RPC_PIPE_INPUT 523 else 524 return 0 525 fi 526 527 while read -t 15 -ru $RPC_PIPE_OUTPUT rsp; do 528 if [[ $rsp == "**STATUS="* ]]; then 529 status[${rsp#*=}]=$rsp 530 if ((++status_number == cmds_number)); then 531 break 532 fi 533 continue 534 fi 535 echo "$rsp" 536 done 537 538 rc=${!status[*]} 539 xtrace_restore 540 [[ $rc == 0 ]] 541} 542 543function rpc_cmd_simple_data_json() { 544 545 local elems="$1[@]" elem 546 local -gA jq_out=() 547 local jq val 548 549 local lvs=( 550 "uuid" 551 "name" 552 "base_bdev" 553 "total_data_clusters" 554 "free_clusters" 555 "block_size" 556 "cluster_size" 557 ) 558 559 local bdev=( 560 "name" 561 "aliases[0]" 562 "block_size" 563 "num_blocks" 564 "uuid" 565 "product_name" 566 ) 567 568 [[ -v $elems ]] || return 1 569 570 for elem in "${!elems}"; do 571 jq="${jq:+$jq,\"\\n\",}\"$elem\",\" \",.[0].$elem" 572 done 573 jq+=',"\n"' 574 575 shift 576 while read -r elem val; do 577 jq_out["$elem"]=$val 578 done < <(rpc_cmd "$@" | jq -jr "$jq") 579 ((${#jq_out[@]} > 0)) || return 1 580} 581 582function NOT() { 583 local es=0 584 585 "$@" || es=$? 586 587 # Logic looks like so: 588 # - return false if command exit successfully 589 # - return false if command exit after receiving a core signal (FIXME: or any signal?) 590 # - return true if command exit with an error 591 592 # This naively assumes that the process doesn't exit with > 128 on its own. 593 if ((es > 128)); then 594 es=$((es & ~128)) 595 case "$es" in 596 3) ;& # SIGQUIT 597 4) ;& # SIGILL 598 6) ;& # SIGABRT 599 8) ;& # SIGFPE 600 9) ;& # SIGKILL 601 11) es=0 ;; # SIGSEGV 602 *) es=1 ;; 603 esac 604 elif [[ -n $EXIT_STATUS ]] && ((es != EXIT_STATUS)); then 605 es=0 606 fi 607 608 # invert error code of any command and also trigger ERR on 0 (unlike bash ! prefix) 609 ((!es == 0)) 610} 611 612function timing() { 613 direction="$1" 614 testname="$2" 615 616 now=$(date +%s) 617 618 if [ "$direction" = "enter" ]; then 619 export timing_stack="${timing_stack};${now}" 620 export test_stack="${test_stack};${testname}" 621 else 622 touch "$output_dir/timing.txt" 623 child_time=$(grep "^${test_stack:1};" $output_dir/timing.txt | awk '{s+=$2} END {print s}') 624 625 start_time=$(echo "$timing_stack" | sed -e 's@^.*;@@') 626 timing_stack=$(echo "$timing_stack" | sed -e 's@;[^;]*$@@') 627 628 elapsed=$((now - start_time - child_time)) 629 echo "${test_stack:1} $elapsed" >> $output_dir/timing.txt 630 631 test_stack=$(echo "$test_stack" | sed -e 's@;[^;]*$@@') 632 fi 633} 634 635function timing_enter() { 636 xtrace_disable 637 timing "enter" "$1" 638 xtrace_restore 639} 640 641function timing_exit() { 642 xtrace_disable 643 timing "exit" "$1" 644 xtrace_restore 645} 646 647function timing_finish() { 648 flamegraph='/usr/local/FlameGraph/flamegraph.pl' 649 if [ -x "$flamegraph" ]; then 650 "$flamegraph" \ 651 --title 'Build Timing' \ 652 --nametype 'Step:' \ 653 --countname seconds \ 654 $output_dir/timing.txt \ 655 > $output_dir/timing.svg 656 fi 657} 658 659function create_test_list() { 660 xtrace_disable 661 # First search all scripts in main SPDK directory. 662 completion=$(grep -shI -d skip --include="*.sh" -e "run_test " $rootdir/*) 663 # Follow up with search in test directory recursively. 664 completion+=$(grep -rshI --include="*.sh" --exclude="*autotest_common.sh" -e "run_test " $rootdir/test) 665 printf "%s" "$completion" | grep -v "#" \ 666 | sed 's/^.*run_test/run_test/' | awk '{print $2}' \ 667 | sed 's/\"//g' | sort > $output_dir/all_tests.txt || true 668 xtrace_restore 669} 670 671function gdb_attach() { 672 gdb -q --batch \ 673 -ex 'handle SIGHUP nostop pass' \ 674 -ex 'handle SIGQUIT nostop pass' \ 675 -ex 'handle SIGPIPE nostop pass' \ 676 -ex 'handle SIGALRM nostop pass' \ 677 -ex 'handle SIGTERM nostop pass' \ 678 -ex 'handle SIGUSR1 nostop pass' \ 679 -ex 'handle SIGUSR2 nostop pass' \ 680 -ex 'handle SIGCHLD nostop pass' \ 681 -ex 'set print thread-events off' \ 682 -ex 'cont' \ 683 -ex 'thread apply all bt' \ 684 -ex 'quit' \ 685 --tty=/dev/stdout \ 686 -p $1 687} 688 689function process_core() { 690 # Note that this always was racy as we can't really sync with the kernel 691 # to see if there's any core queued up for writing. We could check if 692 # collector is running and wait for it explicitly, but it doesn't seem 693 # to be worth the effort. So assume that if we are being called via 694 # trap, as in, when some error has occurred, wait up to 10s for any 695 # potential cores. If we are called just for cleanup at the very end, 696 # don't wait since all the tests ended successfully, hence having any 697 # critical cores lying around is unlikely. 698 ((autotest_es != 0)) && sleep 10 699 700 local coredumps core 701 702 shopt -s nullglob 703 coredumps=("$output_dir/coredumps/"*.bt.txt) 704 shopt -u nullglob 705 706 ((${#coredumps[@]} > 0)) || return 0 707 chmod -R a+r "$output_dir/coredumps" 708 709 for core in "${coredumps[@]}"; do 710 cat <<- BT 711 ##### CORE BT ${core##*/} ##### 712 713 $(<"$core") 714 715 -- 716 BT 717 done 718 return 1 719} 720 721function process_shm() { 722 type=$1 723 id=$2 724 if [ "$type" = "--pid" ]; then 725 id="pid${id}" 726 fi 727 728 shm_files=$(find /dev/shm -name "*.${id}" -printf "%f\n") 729 730 if [[ -z $shm_files ]]; then 731 echo "SHM File for specified PID or shared memory id: ${id} not found!" 732 return 1 733 fi 734 for n in $shm_files; do 735 tar -C /dev/shm/ -cvzf $output_dir/${n}_shm.tar.gz ${n} 736 done 737 return 0 738} 739 740function waitforlisten() { 741 # $1 = process pid 742 if [ -z "$1" ]; then 743 exit 1 744 fi 745 746 local rpc_addr="${2:-$DEFAULT_RPC_ADDR}" 747 748 echo "Waiting for process to start up and listen on UNIX domain socket $rpc_addr..." 749 # turn off trace for this loop 750 xtrace_disable 751 local ret=0 752 local i 753 for ((i = 100; i != 0; i--)); do 754 # if the process is no longer running, then exit the script 755 # since it means the application crashed 756 if ! kill -s 0 $1; then 757 echo "ERROR: process (pid: $1) is no longer running" 758 ret=1 759 break 760 fi 761 762 if $rootdir/scripts/rpc.py -t 1 -s "$rpc_addr" rpc_get_methods &> /dev/null; then 763 break 764 fi 765 766 sleep 0.5 767 done 768 769 xtrace_restore 770 if ((i == 0)); then 771 echo "ERROR: timeout while waiting for process (pid: $1) to start listening on '$rpc_addr'" 772 ret=1 773 fi 774 return $ret 775} 776 777function waitfornbd() { 778 local nbd_name=$1 779 local i 780 781 for ((i = 1; i <= 20; i++)); do 782 if grep -q -w $nbd_name /proc/partitions; then 783 break 784 else 785 sleep 0.1 786 fi 787 done 788 789 # The nbd device is now recognized as a block device, but there can be 790 # a small delay before we can start I/O to that block device. So loop 791 # here trying to read the first block of the nbd block device to a temp 792 # file. Note that dd returns success when reading an empty file, so we 793 # need to check the size of the output file instead. 794 for ((i = 1; i <= 20; i++)); do 795 dd if=/dev/$nbd_name of="$SPDK_TEST_STORAGE/nbdtest" bs=4096 count=1 iflag=direct 796 size=$(stat -c %s "$SPDK_TEST_STORAGE/nbdtest") 797 rm -f "$SPDK_TEST_STORAGE/nbdtest" 798 if [ "$size" != "0" ]; then 799 return 0 800 else 801 sleep 0.1 802 fi 803 done 804 805 return 1 806} 807 808function waitforbdev() { 809 local bdev_name=$1 810 local bdev_timeout=$2 811 local i 812 [[ -z $bdev_timeout ]] && bdev_timeout=2000 # ms 813 814 $rpc_py bdev_wait_for_examine 815 816 if $rpc_py bdev_get_bdevs -b $bdev_name -t $bdev_timeout; then 817 return 0 818 fi 819 820 return 1 821} 822 823function make_filesystem() { 824 local fstype=$1 825 local dev_name=$2 826 local i=0 827 local force 828 829 if [ $fstype = ext4 ]; then 830 force=-F 831 else 832 force=-f 833 fi 834 835 while ! mkfs.${fstype} $force ${dev_name}; do 836 if [ $i -ge 15 ]; then 837 return 1 838 fi 839 i=$((i + 1)) 840 sleep 1 841 done 842 843 return 0 844} 845 846function killprocess() { 847 # $1 = process pid 848 if [ -z "$1" ]; then 849 return 1 850 fi 851 852 if kill -0 $1; then 853 if [ $(uname) = Linux ]; then 854 process_name=$(ps --no-headers -o comm= $1) 855 else 856 process_name=$(ps -c -o command $1 | tail -1) 857 fi 858 if [ "$process_name" = "sudo" ]; then 859 # kill the child process, which is the actual app 860 # (assume $1 has just one child) 861 local child 862 child="$(pgrep -P $1)" 863 echo "killing process with pid $child" 864 kill $child 865 else 866 echo "killing process with pid $1" 867 kill $1 868 fi 869 870 # wait for the process regardless if its the dummy sudo one 871 # or the actual app - it should terminate anyway 872 wait $1 873 else 874 # the process is not there anymore 875 echo "Process with pid $1 is not found" 876 fi 877} 878 879function iscsicleanup() { 880 echo "Cleaning up iSCSI connection" 881 iscsiadm -m node --logout || true 882 iscsiadm -m node -o delete || true 883 rm -rf /var/lib/iscsi/nodes/* 884} 885 886function stop_iscsi_service() { 887 if cat /etc/*-release | grep Ubuntu; then 888 service open-iscsi stop 889 else 890 service iscsid stop 891 fi 892} 893 894function start_iscsi_service() { 895 if cat /etc/*-release | grep Ubuntu; then 896 service open-iscsi start 897 else 898 service iscsid start 899 fi 900} 901 902function rbd_setup() { 903 # $1 = monitor ip address 904 # $2 = name of the namespace 905 if [ -z "$1" ]; then 906 echo "No monitor IP address provided for ceph" 907 exit 1 908 fi 909 if [ -n "$2" ]; then 910 if ip netns list | grep "$2"; then 911 NS_CMD="ip netns exec $2" 912 else 913 echo "No namespace $2 exists" 914 exit 1 915 fi 916 fi 917 918 if hash ceph; then 919 export PG_NUM=128 920 export RBD_POOL=rbd 921 export RBD_NAME=foo 922 $NS_CMD $rootdir/scripts/ceph/stop.sh || true 923 $NS_CMD $rootdir/scripts/ceph/start.sh $1 924 925 $NS_CMD ceph osd pool create $RBD_POOL $PG_NUM || true 926 $NS_CMD rbd create $RBD_NAME --size 1000 927 fi 928} 929 930function rbd_cleanup() { 931 if hash ceph; then 932 $rootdir/scripts/ceph/stop.sh || true 933 rm -f /var/tmp/ceph_raw.img 934 fi 935} 936 937function daos_setup() { 938 # $1 = pool name 939 # $2 = cont name 940 if [ -z "$1" ]; then 941 echo "No pool name provided" 942 exit 1 943 fi 944 if [ -z "$2" ]; then 945 echo "No cont name provided" 946 exit 1 947 fi 948 949 dmg pool create --size=10G $1 || true 950 daos container create --type=POSIX --label=$2 $1 || true 951} 952 953function daos_cleanup() { 954 local pool=${1:-testpool} 955 local cont=${2:-testcont} 956 957 daos container destroy -f $pool $cont || true 958 sudo dmg pool destroy -f $pool || true 959} 960 961function _start_stub() { 962 # Disable ASLR for multi-process testing. SPDK does support using DPDK multi-process, 963 # but ASLR can still be unreliable in some cases. 964 # We will reenable it again after multi-process testing is complete in kill_stub(). 965 # Save current setting so it can be restored upon calling kill_stub(). 966 _randomize_va_space=$(< /proc/sys/kernel/randomize_va_space) 967 echo 0 > /proc/sys/kernel/randomize_va_space 968 $rootdir/test/app/stub/stub $1 & 969 stubpid=$! 970 echo Waiting for stub to ready for secondary processes... 971 while ! [ -e /var/run/spdk_stub0 ]; do 972 # If stub dies while we wait, bail 973 [[ -e /proc/$stubpid ]] || return 1 974 sleep 1s 975 done 976 echo done. 977} 978 979function start_stub() { 980 if ! _start_stub "$@"; then 981 echo "stub failed" >&2 982 return 1 983 fi 984} 985 986function kill_stub() { 987 if [[ -e /proc/$stubpid ]]; then 988 kill $1 $stubpid 989 wait $stubpid 990 fi 2> /dev/null || : 991 rm -f /var/run/spdk_stub0 992 # Re-enable ASLR now that we are done with multi-process testing 993 # Note: "1" enables ASLR w/o randomizing data segments, "2" adds data segment 994 # randomizing and is the default on all recent Linux kernels 995 echo "${_randomize_va_space:-2}" > /proc/sys/kernel/randomize_va_space 996} 997 998function run_test() { 999 if [ $# -le 1 ]; then 1000 echo "Not enough parameters" 1001 echo "usage: run_test test_name test_script [script_params]" 1002 exit 1 1003 fi 1004 1005 xtrace_disable 1006 local test_name="$1" 1007 shift 1008 1009 if [ -n "$test_domain" ]; then 1010 export test_domain="${test_domain}.${test_name}" 1011 else 1012 export test_domain="$test_name" 1013 fi 1014 1015 timing_enter $test_name 1016 echo "************************************" 1017 echo "START TEST $test_name" 1018 echo "************************************" 1019 xtrace_restore 1020 time "$@" 1021 xtrace_disable 1022 echo "************************************" 1023 echo "END TEST $test_name" 1024 echo "************************************" 1025 timing_exit $test_name 1026 1027 export test_domain=${test_domain%"$test_name"} 1028 if [ -n "$test_domain" ]; then 1029 export test_domain=${test_domain%?} 1030 fi 1031 1032 if [ -z "$test_domain" ]; then 1033 echo "top_level $test_name" >> $output_dir/test_completions.txt 1034 else 1035 echo "$test_domain $test_name" >> $output_dir/test_completions.txt 1036 fi 1037 xtrace_restore 1038} 1039 1040function skip_run_test_with_warning() { 1041 echo "WARNING: $1" 1042 echo "Test run may fail if run with autorun.sh" 1043 echo "Please check your $rootdir/test/common/skipped_tests.txt" 1044} 1045 1046function print_backtrace() { 1047 # if errexit is not enabled, don't print a backtrace 1048 [[ "$-" =~ e ]] || return 0 1049 1050 local args=("${BASH_ARGV[@]}") 1051 1052 xtrace_disable 1053 # Reset IFS in case we were called from an environment where it was modified 1054 IFS=" "$'\t'$'\n' 1055 echo "========== Backtrace start: ==========" 1056 echo "" 1057 for ((i = 1; i < ${#FUNCNAME[@]}; i++)); do 1058 local func="${FUNCNAME[$i]}" 1059 local line_nr="${BASH_LINENO[$((i - 1))]}" 1060 local src="${BASH_SOURCE[$i]}" 1061 local bt="" cmdline=() 1062 1063 if [[ -f $src ]]; then 1064 bt=$(nl -w 4 -ba -nln $src | grep -B 5 -A 5 "^${line_nr}[^0-9]" \ 1065 | sed "s/^/ /g" | sed "s/^ $line_nr /=> $line_nr /g") 1066 fi 1067 1068 # If extdebug set the BASH_ARGC[i], try to fetch all the args 1069 if ((BASH_ARGC[i] > 0)); then 1070 # Use argc as index to reverse the stack 1071 local argc=${BASH_ARGC[i]} arg 1072 for arg in "${args[@]::BASH_ARGC[i]}"; do 1073 cmdline[argc--]="[\"$arg\"]" 1074 done 1075 args=("${args[@]:BASH_ARGC[i]}") 1076 fi 1077 1078 echo "in $src:$line_nr -> $func($( 1079 IFS="," 1080 printf '%s\n' "${cmdline[*]:-[]}" 1081 ))" 1082 echo " ..." 1083 echo "${bt:-backtrace unavailable}" 1084 echo " ..." 1085 done 1086 echo "" 1087 echo "========== Backtrace end ==========" 1088 xtrace_restore 1089 return 0 1090} 1091 1092function waitforserial() { 1093 local i=0 1094 local nvme_device_counter=1 nvme_devices=0 1095 if [[ -n "$2" ]]; then 1096 nvme_device_counter=$2 1097 fi 1098 1099 # Wait initially for min 4s to make sure all devices are ready for use. It seems 1100 # that we may be racing with a kernel where in some cases immediate disconnect may 1101 # leave dangling subsystem with no-op block devices which can't be used nor removed 1102 # (unless kernel is rebooted) and which start to negatively affect all the tests. 1103 sleep 4 1104 while ((i++ <= 15)); do 1105 nvme_devices=$(lsblk -l -o NAME,SERIAL | grep -c "$1") 1106 ((nvme_devices == nvme_device_counter)) && return 0 1107 if ((nvme_devices > nvme_device_counter)); then 1108 echo "$nvme_device_counter device(s) expected, found $nvme_devices" >&2 1109 fi 1110 echo "Waiting for devices" 1111 sleep 1 1112 done 1113 return 1 1114} 1115 1116function waitforserial_disconnect() { 1117 local i=0 1118 while lsblk -o NAME,SERIAL | grep -q -w $1; do 1119 [ $i -lt 15 ] || break 1120 i=$((i + 1)) 1121 echo "Waiting for disconnect devices" 1122 sleep 1 1123 done 1124 1125 if lsblk -l -o NAME,SERIAL | grep -q -w $1; then 1126 return 1 1127 fi 1128 1129 return 0 1130} 1131 1132function waitforblk() { 1133 local i=0 1134 while ! lsblk -l -o NAME | grep -q -w $1; do 1135 [ $i -lt 15 ] || break 1136 i=$((i + 1)) 1137 sleep 1 1138 done 1139 1140 if ! lsblk -l -o NAME | grep -q -w $1; then 1141 return 1 1142 fi 1143 1144 return 0 1145} 1146 1147function waitforblk_disconnect() { 1148 local i=0 1149 while lsblk -l -o NAME | grep -q -w $1; do 1150 [ $i -lt 15 ] || break 1151 i=$((i + 1)) 1152 sleep 1 1153 done 1154 1155 if lsblk -l -o NAME | grep -q -w $1; then 1156 return 1 1157 fi 1158 1159 return 0 1160} 1161 1162function waitforfile() { 1163 local i=0 1164 while [ ! -e $1 ]; do 1165 [ $i -lt 200 ] || break 1166 i=$((i + 1)) 1167 sleep 0.1 1168 done 1169 1170 if [ ! -e $1 ]; then 1171 return 1 1172 fi 1173 1174 return 0 1175} 1176 1177function fio_config_gen() { 1178 local config_file=$1 1179 local workload=$2 1180 local bdev_type=$3 1181 local env_context=$4 1182 local fio_dir=$CONFIG_FIO_SOURCE_DIR 1183 1184 if [ -e "$config_file" ]; then 1185 echo "Configuration File Already Exists!: $config_file" 1186 return 1 1187 fi 1188 1189 if [ -z "$workload" ]; then 1190 workload=randrw 1191 fi 1192 1193 if [ -n "$env_context" ]; then 1194 env_context="env_context=$env_context" 1195 fi 1196 1197 touch $1 1198 1199 cat > $1 << EOL 1200[global] 1201thread=1 1202$env_context 1203group_reporting=1 1204direct=1 1205norandommap=1 1206percentile_list=50:99:99.9:99.99:99.999 1207time_based=1 1208ramp_time=0 1209EOL 1210 1211 if [ "$workload" == "verify" ]; then 1212 cat <<- EOL >> $config_file 1213 verify=sha1 1214 verify_backlog=1024 1215 rw=randwrite 1216 EOL 1217 1218 # To avoid potential data race issue due to the AIO device 1219 # flush mechanism, add the flag to serialize the writes. 1220 # This is to fix the intermittent IO failure issue of #935 1221 if [ "$bdev_type" == "AIO" ]; then 1222 if [[ $($fio_dir/fio --version) == *"fio-3"* ]]; then 1223 echo "serialize_overlap=1" >> $config_file 1224 fi 1225 fi 1226 elif [ "$workload" == "trim" ]; then 1227 echo "rw=trimwrite" >> $config_file 1228 else 1229 echo "rw=$workload" >> $config_file 1230 fi 1231} 1232 1233function fio_plugin() { 1234 # Setup fio binary cmd line 1235 local fio_dir=$CONFIG_FIO_SOURCE_DIR 1236 # gcc and clang uses different sanitizer libraries 1237 local sanitizers=(libasan libclang_rt.asan) 1238 local plugin=$1 1239 shift 1240 1241 local asan_lib= 1242 for sanitizer in "${sanitizers[@]}"; do 1243 asan_lib=$(ldd $plugin | grep $sanitizer | awk '{print $3}') 1244 if [[ -n "$asan_lib" ]]; then 1245 break 1246 fi 1247 done 1248 1249 # Preload the sanitizer library to fio if fio_plugin was compiled with it 1250 LD_PRELOAD="$asan_lib $plugin" "$fio_dir"/fio "$@" 1251} 1252 1253function fio_bdev() { 1254 fio_plugin "$rootdir/build/fio/spdk_bdev" "$@" 1255} 1256 1257function fio_nvme() { 1258 fio_plugin "$rootdir/build/fio/spdk_nvme" "$@" 1259} 1260 1261function get_lvs_free_mb() { 1262 local lvs_uuid=$1 1263 local lvs_info 1264 local fc 1265 local cs 1266 lvs_info=$($rpc_py bdev_lvol_get_lvstores) 1267 fc=$(jq ".[] | select(.uuid==\"$lvs_uuid\") .free_clusters" <<< "$lvs_info") 1268 cs=$(jq ".[] | select(.uuid==\"$lvs_uuid\") .cluster_size" <<< "$lvs_info") 1269 1270 # Change to MB's 1271 free_mb=$((fc * cs / 1024 / 1024)) 1272 echo "$free_mb" 1273} 1274 1275function get_bdev_size() { 1276 local bdev_name=$1 1277 local bdev_info 1278 local bs 1279 local nb 1280 bdev_info=$($rpc_py bdev_get_bdevs -b $bdev_name) 1281 bs=$(jq ".[] .block_size" <<< "$bdev_info") 1282 nb=$(jq ".[] .num_blocks" <<< "$bdev_info") 1283 1284 # Change to MB's 1285 bdev_size=$((bs * nb / 1024 / 1024)) 1286 echo "$bdev_size" 1287} 1288 1289function autotest_cleanup() { 1290 local autotest_es=$? 1291 xtrace_disable 1292 1293 # catch any stray core files and kill all remaining SPDK processes. Update 1294 # autotest_es in case autotest reported success but cores and/or processes 1295 # were left behind regardless. 1296 1297 process_core || autotest_es=1 1298 reap_spdk_processes || autotest_es=1 1299 1300 $rootdir/scripts/setup.sh reset 1301 $rootdir/scripts/setup.sh cleanup 1302 if [ $(uname -s) = "Linux" ]; then 1303 if [[ $SPDK_TEST_USE_IGB_UIO -eq 1 ]]; then 1304 [[ -e /sys/module/igb_uio ]] && rmmod igb_uio 1305 else 1306 modprobe -r uio_pci_generic 1307 fi 1308 fi 1309 rm -rf "$asan_suppression_file" 1310 if [[ -n $old_core_pattern ]]; then 1311 echo "$old_core_pattern" > /proc/sys/kernel/core_pattern 1312 fi 1313 if [[ -e /proc/$udevadm_pid/status ]]; then 1314 kill "$udevadm_pid" || : 1315 fi 1316 1317 shopt -s nullglob 1318 local storage_fallback_purge=("${TMPDIR:-/tmp}/spdk."??????) 1319 shopt -u nullglob 1320 1321 if ((${#storage_fallback_purge[@]} > 0)); then 1322 rm -rf "${storage_fallback_purge[@]}" 1323 fi 1324 1325 if ((autotest_es)); then 1326 if [[ $(uname) == FreeBSD ]]; then 1327 ps aux 1328 elif [[ $(uname) == Linux ]]; then 1329 # Get more detailed view 1330 grep . /proc/[0-9]*/status 1331 # Dump some extra info into kernel log 1332 echo "######## Autotest Cleanup Dump ########" > /dev/kmsg 1333 # Show cpus backtraces 1334 echo l > /proc/sysrq-trigger 1335 # Show mem usage 1336 echo m > /proc/sysrq-trigger 1337 # show task states 1338 echo t > /proc/sysrq-trigger 1339 # show blocked tasks 1340 echo w > /proc/sysrq-trigger 1341 1342 fi > "$output_dir/proc_list.txt" 2>&1 || : 1343 fi 1344 xtrace_restore 1345 return $autotest_es 1346} 1347 1348function freebsd_update_contigmem_mod() { 1349 if [ $(uname) = FreeBSD ]; then 1350 kldunload contigmem.ko || true 1351 if [ -n "$SPDK_RUN_EXTERNAL_DPDK" ]; then 1352 cp -f "$SPDK_RUN_EXTERNAL_DPDK/kmod/contigmem.ko" /boot/modules/ 1353 cp -f "$SPDK_RUN_EXTERNAL_DPDK/kmod/contigmem.ko" /boot/kernel/ 1354 cp -f "$SPDK_RUN_EXTERNAL_DPDK/kmod/nic_uio.ko" /boot/modules/ 1355 cp -f "$SPDK_RUN_EXTERNAL_DPDK/kmod/nic_uio.ko" /boot/kernel/ 1356 else 1357 cp -f "$rootdir/dpdk/build/kmod/contigmem.ko" /boot/modules/ 1358 cp -f "$rootdir/dpdk/build/kmod/contigmem.ko" /boot/kernel/ 1359 cp -f "$rootdir/dpdk/build/kmod/nic_uio.ko" /boot/modules/ 1360 cp -f "$rootdir/dpdk/build/kmod/nic_uio.ko" /boot/kernel/ 1361 fi 1362 fi 1363} 1364 1365function get_nvme_name_from_bdf() { 1366 blkname=() 1367 1368 nvme_devs=$(lsblk -d --output NAME | grep "^nvme") || true 1369 if [ -z "$nvme_devs" ]; then 1370 return 1371 fi 1372 for dev in $nvme_devs; do 1373 link_name=$(readlink /sys/block/$dev/device/device) || true 1374 if [ -z "$link_name" ]; then 1375 link_name=$(readlink /sys/block/$dev/device) 1376 fi 1377 bdf=$(basename "$link_name") 1378 if [ "$bdf" = "$1" ]; then 1379 blkname+=($dev) 1380 fi 1381 done 1382 1383 printf '%s\n' "${blkname[@]}" 1384} 1385 1386function get_nvme_ctrlr_from_bdf() { 1387 bdf_sysfs_path=$(readlink -f /sys/class/nvme/nvme* | grep "$1/nvme/nvme") 1388 if [[ -z "$bdf_sysfs_path" ]]; then 1389 return 1390 fi 1391 1392 printf '%s\n' "$(basename $bdf_sysfs_path)" 1393} 1394 1395# Get BDF addresses of all NVMe drives currently attached to 1396# uio-pci-generic or vfio-pci 1397function get_nvme_bdfs() { 1398 xtrace_disable 1399 bdfs=$(jq -r .config[].params.traddr <<< $($rootdir/scripts/gen_nvme.sh)) 1400 if [[ -z $bdfs ]]; then 1401 echo "No devices to test on!" 1402 exit 1 1403 fi 1404 echo "$bdfs" 1405 xtrace_restore 1406} 1407 1408# Same as function above, but just get the first disks BDF address 1409function get_first_nvme_bdf() { 1410 head -1 <<< "$(get_nvme_bdfs)" 1411} 1412 1413function nvme_namespace_revert() { 1414 $rootdir/scripts/setup.sh 1415 sleep 1 1416 bdfs=$(get_nvme_bdfs) 1417 1418 $rootdir/scripts/setup.sh reset 1419 1420 for bdf in $bdfs; do 1421 nvme_ctrlr=/dev/$(get_nvme_ctrlr_from_bdf ${bdf}) 1422 if [[ -z "$nvme_ctrlr" ]]; then 1423 continue 1424 fi 1425 1426 # Check Optional Admin Command Support for Namespace Management 1427 oacs=$(nvme id-ctrl ${nvme_ctrlr} | grep oacs | cut -d: -f2) 1428 oacs_ns_manage=$((oacs & 0x8)) 1429 1430 if [[ "$oacs_ns_manage" -ne 0 ]]; then 1431 # This assumes every NVMe controller contains single namespace, 1432 # encompassing Total NVM Capacity and formatted as 512 block size. 1433 # 512 block size is needed for test/vhost/vhost_boot.sh to 1434 # successfully run. 1435 1436 unvmcap=$(nvme id-ctrl ${nvme_ctrlr} | grep unvmcap | cut -d: -f2) 1437 if [[ "$unvmcap" -eq 0 ]]; then 1438 # All available space already used 1439 continue 1440 fi 1441 tnvmcap=$(nvme id-ctrl ${nvme_ctrlr} | grep tnvmcap | cut -d: -f2) 1442 blksize=512 1443 1444 size=$((tnvmcap / blksize)) 1445 1446 nvme detach-ns ${nvme_ctrlr} -n 0xffffffff -c 0 || true 1447 nvme delete-ns ${nvme_ctrlr} -n 0xffffffff || true 1448 nvme create-ns ${nvme_ctrlr} -s ${size} -c ${size} -b ${blksize} 1449 nvme attach-ns ${nvme_ctrlr} -n 1 -c 0 1450 nvme reset ${nvme_ctrlr} 1451 waitforfile "${nvme_ctrlr}n1" 1452 fi 1453 done 1454} 1455 1456# Get BDFs based on device ID, such as 0x0a54 1457function get_nvme_bdfs_by_id() { 1458 local bdfs=() 1459 1460 for bdf in $(get_nvme_bdfs); do 1461 device=$(cat /sys/bus/pci/devices/$bdf/device) || true 1462 if [[ "$device" == "$1" ]]; then 1463 bdfs+=($bdf) 1464 fi 1465 done 1466 1467 printf '%s\n' "${bdfs[@]}" 1468} 1469 1470function opal_revert_cleanup() { 1471 # The OPAL CI tests is only used for P4510 devices. 1472 mapfile -t bdfs < <(get_nvme_bdfs_by_id 0x0a54) 1473 if [[ -z ${bdfs[0]} ]]; then 1474 return 0 1475 fi 1476 1477 $SPDK_BIN_DIR/spdk_tgt & 1478 spdk_tgt_pid=$! 1479 waitforlisten $spdk_tgt_pid 1480 1481 bdf_id=0 1482 for bdf in "${bdfs[@]}"; do 1483 $rootdir/scripts/rpc.py bdev_nvme_attach_controller -b "nvme"${bdf_id} -t "pcie" -a ${bdf} 1484 # Ignore if this fails. 1485 $rootdir/scripts/rpc.py bdev_nvme_opal_revert -b "nvme"${bdf_id} -p test || true 1486 ((++bdf_id)) 1487 done 1488 1489 killprocess $spdk_tgt_pid 1490} 1491 1492function pap() { 1493 while read -r file; do 1494 cat <<- FILE 1495 --- $file --- 1496 $(<"$file") 1497 --- $file --- 1498 FILE 1499 rm -f "$file" 1500 done < <(find "$@" -type f | sort -u) 1501} 1502 1503function get_proc_paths() { 1504 local procs proc 1505 if [[ $(uname -s) == Linux ]]; then 1506 for proc in /proc/[0-9]*; do 1507 [[ -e $proc/exe ]] || continue 1508 procs[${proc##*/}]=$(readlink -f "$proc/exe") 1509 done 1510 elif [[ $(uname -s) == FreeBSD ]]; then 1511 while read -r proc _ _ path; do 1512 [[ -e $path ]] || continue 1513 procs[proc]=$path 1514 done < <(procstat -ab) 1515 fi 1516 1517 for proc in "${!procs[@]}"; do 1518 echo "$proc" "${procs[proc]}" 1519 done 1520} 1521 1522is_exec_file() { [[ -f $1 && $(file "$1") =~ ELF.+executable ]]; } 1523 1524function reap_spdk_processes() { 1525 local bins bin 1526 local misc_bins 1527 1528 while read -r bin; do 1529 is_exec_file "$bin" && misc_bins+=("$bin") 1530 done < <(find "$rootdir"/test/{app,env,event} -type f) 1531 1532 mapfile -t bins < <(readlink -f "$SPDK_BIN_DIR/"* "$SPDK_EXAMPLE_DIR/"* "${misc_bins[@]}") 1533 1534 local spdk_pid spdk_pids path 1535 while read -r spdk_pid path; do 1536 if [[ ${bins[*]/$path/} != "${bins[*]}" ]]; then 1537 echo "$path is still up ($spdk_pid), killing" 1538 spdk_pids[spdk_pid]=$path 1539 fi 1540 done < <(get_proc_paths) 1541 1542 ((${#spdk_pids[@]} > 0)) || return 0 1543 1544 kill -SIGTERM "${!spdk_pids[@]}" 2> /dev/null || : 1545 # Wait a bit and then use the stick 1546 sleep 2 1547 kill -SIGKILL "${!spdk_pids[@]}" 2> /dev/null || : 1548 1549 return 1 1550} 1551 1552function is_block_zoned() { 1553 local device=$1 1554 1555 [[ -e /sys/block/$device/queue/zoned ]] || return 1 1556 [[ $(< "/sys/block/$device/queue/zoned") != none ]] 1557} 1558 1559function get_zoned_devs() { 1560 local -gA zoned_devs=() 1561 local nvme bdf 1562 1563 for nvme in /sys/block/nvme*; do 1564 if is_block_zoned "${nvme##*/}"; then 1565 zoned_devs["${nvme##*/}"]=$(< "$nvme/device/address") 1566 fi 1567 done 1568} 1569 1570# Define temp storage for all the tests. Look for 2GB at minimum 1571set_test_storage "${TEST_MIN_STORAGE_SIZE:-$((1 << 31))}" 1572 1573set -o errtrace 1574shopt -s extdebug 1575trap "trap - ERR; print_backtrace >&2" ERR 1576 1577PS4=' \t -- ${BASH_SOURCE#${BASH_SOURCE%/*/*}/}@${LINENO} -- \$ ' 1578if $SPDK_AUTOTEST_X; then 1579 # explicitly enable xtraces, overriding any tracking information. 1580 unset XTRACE_DISABLED 1581 unset XTRACE_NESTING_LEVEL 1582 xtrace_fd 1583 xtrace_enable 1584else 1585 xtrace_restore 1586fi 1587