1#!/usr/bin/env bash 2rootdir=$(readlink -f "$(dirname "$0")/../") 3 4shopt -s nullglob extglob 5 6fio_config() { 7 local devs=("$@") dev 8 9 cat <<- FIO 10 [global] 11 thread=1 12 invalidate=1 13 rw=$testtype 14 time_based=1 15 runtime=$runtime 16 ioengine=libaio 17 direct=1 18 bs=$blocksize 19 iodepth=$iodepth 20 norandommap=$((verify == 1 ? 0 : 1)) 21 numjobs=$numjobs 22 verify_dump=1 23 verify_backlog=512 24 verify_state_save=0 25 FIO 26 27 if ((verify == 1)); then 28 cat <<- FIO 29 do_verify=$verify 30 verify=crc32c-intel 31 FIO 32 fi 33 34 for dev in "${!devs[@]}"; do 35 cat <<- FIO 36 [job$dev] 37 filename=/dev/${devs[dev]} 38 FIO 39 done 40} 41 42run_fio() { 43 fio_config "$@" | fio - 44} 45 46get_iscsi() { 47 while read -r; do 48 [[ $REPLY =~ "Attached scsi disk "(sd[a-z]+) ]] && echo "${BASH_REMATCH[1]}" 49 done < <(iscsiadm -m session -P 3) 50} 51 52get_nvme() { 53 local blocks nvme nvme_sub 54 for nvme in /sys/block/nvme*; do 55 # Some kernels expose hidden fabrics devices ("nvmeXcXnX") under sysfs - skip them. 56 if (($(< "$nvme/hidden") == 1)); then 57 continue 58 fi 59 # Make sure we touch only the block devices which belong to bdev subsystem. 60 [[ $(< "$nvme/device/model") == "SPDK bdev Controller"* ]] || continue 61 blocks+=("${nvme##*/}") 62 done 63 printf '%s\n' "${blocks[@]}" 64} 65 66get_devices() { 67 local devs=("$@") 68 69 if ((${#devs[@]} == 0)); then 70 case "$protocol" in 71 iscsi) devs=($(get_iscsi)) ;; 72 nvmf) devs=($(get_nvme)) ;; 73 *) ;; 74 esac 75 fi 76 printf '%s\n' "${devs[@]}" 77} 78 79configure_devices() { 80 local devs=("$@") dev qd 81 82 if [[ -e $rootdir/scripts/sync_dev_uevents.sh ]]; then 83 "$rootdir/scripts/sync_dev_uevents.sh" block/disk "${devs[@]}" 84 fi > /dev/null 85 86 for dev in "${devs[@]}"; do 87 qd=128 88 # Disable all merge tries" 89 echo 2 > "/sys/block/$dev/queue/nomerges" 90 # FIXME: nr_requests already has its default value at 128. Also, when no 91 # scheduler is associated with the device this value cannot be changed 92 # and is automatically adjusted as well. 93 # echo 128 > "/sys/block/$dev/queue/nr_requests" 94 if [[ -e /sys/block/$dev/device/queue_depth ]]; then 95 # FIXME: Is this really needed though? Can't we use the default? This is not 96 # very deterministic as depending on the device we may end up with different 97 # qd in the range of 1-128. 98 while ((qd > 0)) && ! echo "$qd" > "/sys/block/$dev/device/queue_depth"; do 99 ((--qd)) 100 done 2> /dev/null 101 if ((qd == 0)); then 102 printf 'Failed to set queue_depth (%s)\n' "$dev" 103 return 1 104 fi 105 printf 'queue_depth set to %u (%s)\n' "$qd" "$dev" 106 else 107 printf 'Could not set queue depth (%s)\n' "$dev" >&2 108 fi 109 echo none > "/sys/block/$dev/queue/scheduler" 110 done 111} 112 113# Defaults 114blocksize=4096 115iodepth=1 116numjobs=1 117protocol="nvmf" 118runtime=1 119testtype="read" 120verify=0 121 122# Keep short args compatible with fio.py 123while getopts :i:d:n:p:r:t:v arg; do 124 case "$arg" in 125 i) blocksize=$OPTARG ;; 126 d) iodepth=$OPTARG ;; 127 n) numjobs=$OPTARG ;; 128 p) protocol=$OPTARG ;; 129 r) runtime=$OPTARG ;; 130 t) testtype=$OPTARG ;; 131 v) verify=1 ;; 132 *) ;; 133 esac 134done 135shift $((OPTIND - 1)) 136 137devices=($(get_devices "$@")) 138if ((${#devices[@]} == 0)); then 139 printf '* No devices were found for the test, aborting\n' >&2 140 exit 1 141fi 142 143fio_config "${devices[@]}" 144configure_devices "${devices[@]}" && run_fio "${devices[@]}" 145