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