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