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