1*94c4a1e1SFrank Piva#!/bin/bash 2*94c4a1e1SFrank Piva# SPDX-License-Identifier: MIT or GPL-2.0-only 3*94c4a1e1SFrank Piva 4*94c4a1e1SFrank Pivadeclare -A TEST_RUN 5*94c4a1e1SFrank Piva 6*94c4a1e1SFrank Pivadeclare -A FIO_TERSE_FIELDS 7*94c4a1e1SFrank PivaFIO_TERSE_FIELDS=( 8*94c4a1e1SFrank Piva # Read status 9*94c4a1e1SFrank Piva ["read io"]=6 10*94c4a1e1SFrank Piva ["read bandwidth"]=7 11*94c4a1e1SFrank Piva ["read iops"]=8 12*94c4a1e1SFrank Piva ["read runtime"]=9 13*94c4a1e1SFrank Piva ["read slat min"]=10 14*94c4a1e1SFrank Piva ["read slat max"]=11 15*94c4a1e1SFrank Piva ["read slat mean"]=12 16*94c4a1e1SFrank Piva ["read slat stdev"]=13 17*94c4a1e1SFrank Piva ["read clat min"]=14 18*94c4a1e1SFrank Piva ["read clat max"]=15 19*94c4a1e1SFrank Piva ["read clat mean"]=16 20*94c4a1e1SFrank Piva ["read clat stdev"]=17 21*94c4a1e1SFrank Piva # read clat percentiles are 18-37 22*94c4a1e1SFrank Piva ["read lat min"]=38 23*94c4a1e1SFrank Piva ["read lat max"]=39 24*94c4a1e1SFrank Piva ["read lat mean"]=40 25*94c4a1e1SFrank Piva ["read lat stdev"]=41 26*94c4a1e1SFrank Piva ["read bandwidth min"]=42 27*94c4a1e1SFrank Piva ["read bandwidth max"]=43 28*94c4a1e1SFrank Piva ["read bandwidth %"]=44 29*94c4a1e1SFrank Piva ["read bandwidth mean"]=45 30*94c4a1e1SFrank Piva ["read bandwidth stdev"]=46 31*94c4a1e1SFrank Piva 32*94c4a1e1SFrank Piva # Write status 33*94c4a1e1SFrank Piva ["write io"]=47 34*94c4a1e1SFrank Piva ["write bandwidth"]=48 35*94c4a1e1SFrank Piva ["write iops"]=49 36*94c4a1e1SFrank Piva ["write runtime"]=50 37*94c4a1e1SFrank Piva ["write slat min"]=51 38*94c4a1e1SFrank Piva ["write slat max"]=52 39*94c4a1e1SFrank Piva ["write slat mean"]=53 40*94c4a1e1SFrank Piva ["write slat stdev"]=54 41*94c4a1e1SFrank Piva ["write clat min"]=55 42*94c4a1e1SFrank Piva ["write clat max"]=56 43*94c4a1e1SFrank Piva ["write clat mean"]=57 44*94c4a1e1SFrank Piva ["write clat stdev"]=58 45*94c4a1e1SFrank Piva # write clat percentiles are 59-78 46*94c4a1e1SFrank Piva ["write lat min"]=79 47*94c4a1e1SFrank Piva ["write lat max"]=80 48*94c4a1e1SFrank Piva ["write lat mean"]=81 49*94c4a1e1SFrank Piva ["write lat stdev"]=82 50*94c4a1e1SFrank Piva ["write bandwidth min"]=83 51*94c4a1e1SFrank Piva ["write bandwidth max"]=84 52*94c4a1e1SFrank Piva ["write bandwidth %"]=85 53*94c4a1e1SFrank Piva ["write bandwidth mean"]=86 54*94c4a1e1SFrank Piva ["write bandwidth stdev"]=87 55*94c4a1e1SFrank Piva 56*94c4a1e1SFrank Piva # Trim status 57*94c4a1e1SFrank Piva ["trim io"]=88 58*94c4a1e1SFrank Piva ["trim bandwidth"]=89 59*94c4a1e1SFrank Piva ["trim iops"]=90 60*94c4a1e1SFrank Piva ["trim runtime"]=91 61*94c4a1e1SFrank Piva ["trim slat min"]=92 62*94c4a1e1SFrank Piva ["trim slat max"]=93 63*94c4a1e1SFrank Piva ["trim slat mean"]=94 64*94c4a1e1SFrank Piva ["trim slat stdev"]=95 65*94c4a1e1SFrank Piva ["trim clat min"]=96 66*94c4a1e1SFrank Piva ["trim clat max"]=97 67*94c4a1e1SFrank Piva ["trim clat mean"]=98 68*94c4a1e1SFrank Piva ["trim clat stdev"]=99 69*94c4a1e1SFrank Piva # trim clat percentiles are 100-119 70*94c4a1e1SFrank Piva ["trim lat min"]=120 71*94c4a1e1SFrank Piva ["trim lat max"]=121 72*94c4a1e1SFrank Piva ["trim lat mean"]=122 73*94c4a1e1SFrank Piva ["trim lat stdev"]=123 74*94c4a1e1SFrank Piva ["trim bandwidth min"]=124 75*94c4a1e1SFrank Piva ["trim bandwidth max"]=125 76*94c4a1e1SFrank Piva ["trim bandwidth %"]=126 77*94c4a1e1SFrank Piva ["trim bandwidth mean"]=127 78*94c4a1e1SFrank Piva ["trim bandwidth stdev"]=128 79*94c4a1e1SFrank Piva 80*94c4a1e1SFrank Piva # CPU usage 81*94c4a1e1SFrank Piva ["user cpu"]=129 82*94c4a1e1SFrank Piva ["system cpu"]=130 83*94c4a1e1SFrank Piva ["context switches"]=131 84*94c4a1e1SFrank Piva ["major page faults"]=132 85*94c4a1e1SFrank Piva ["minor page faults"]=133 86*94c4a1e1SFrank Piva 87*94c4a1e1SFrank Piva # IO depth distribution 88*94c4a1e1SFrank Piva ["io depth <=1"]=134 89*94c4a1e1SFrank Piva ["io depth 2"]=135 90*94c4a1e1SFrank Piva ["io depth 4"]=136 91*94c4a1e1SFrank Piva ["io depth 8"]=137 92*94c4a1e1SFrank Piva ["io depth 16"]=138 93*94c4a1e1SFrank Piva ["io depth 32"]=139 94*94c4a1e1SFrank Piva ["io depth >=64"]=140 95*94c4a1e1SFrank Piva 96*94c4a1e1SFrank Piva # IO latency distribution 97*94c4a1e1SFrank Piva ["io latency <=2 us"]=141 98*94c4a1e1SFrank Piva ["io latency 4 us"]=142 99*94c4a1e1SFrank Piva ["io latency 10 us"]=143 100*94c4a1e1SFrank Piva ["io latency 20 us"]=144 101*94c4a1e1SFrank Piva ["io latency 50 us"]=145 102*94c4a1e1SFrank Piva ["io latency 100 us"]=146 103*94c4a1e1SFrank Piva ["io latency 250 us"]=147 104*94c4a1e1SFrank Piva ["io latency 500 us"]=148 105*94c4a1e1SFrank Piva ["io latency 750 us"]=149 106*94c4a1e1SFrank Piva ["io latency 1000 us"]=150 107*94c4a1e1SFrank Piva ["io latency <=2 ms"]=151 108*94c4a1e1SFrank Piva ["io latency 4 ms"]=152 109*94c4a1e1SFrank Piva ["io latency 10 ms"]=153 110*94c4a1e1SFrank Piva ["io latency 20 ms"]=154 111*94c4a1e1SFrank Piva ["io latency 50 ms"]=155 112*94c4a1e1SFrank Piva ["io latency 100 ms"]=156 113*94c4a1e1SFrank Piva ["io latency 250 ms"]=157 114*94c4a1e1SFrank Piva ["io latency 500 ms"]=158 115*94c4a1e1SFrank Piva ["io latency 750 ms"]=159 116*94c4a1e1SFrank Piva ["io latency 1000 ms"]=160 117*94c4a1e1SFrank Piva ["io latency 2000 ms"]=161 118*94c4a1e1SFrank Piva ["io latency >=2000 ms"]=162 119*94c4a1e1SFrank Piva 120*94c4a1e1SFrank Piva # Disk utilization (11 fields per disk) 121*94c4a1e1SFrank Piva) 122*94c4a1e1SFrank Piva 123*94c4a1e1SFrank PivaFIO_OUTPUT="$TEST_DIR/.fio_perf" 124*94c4a1e1SFrank Piva 125*94c4a1e1SFrank Piva_fio_perf_report() { 126*94c4a1e1SFrank Piva # If there is more than one group, we don't know what to report. 127*94c4a1e1SFrank Piva if [[ $(wc -l < "$FIO_OUTPUT") -gt 1 ]]; then 128*94c4a1e1SFrank Piva echo "_fio_perf: too many terse lines" >&2 129*94c4a1e1SFrank Piva return 130*94c4a1e1SFrank Piva fi 131*94c4a1e1SFrank Piva 132*94c4a1e1SFrank Piva local name field value 133*94c4a1e1SFrank Piva for name in "${FIO_PERF_FIELDS[@]}"; do 134*94c4a1e1SFrank Piva field="${FIO_TERSE_FIELDS["$name"]}" 135*94c4a1e1SFrank Piva if [[ -z $field ]]; then 136*94c4a1e1SFrank Piva echo "_fio_perf: unknown fio terse field '$name'" >&2 137*94c4a1e1SFrank Piva continue 138*94c4a1e1SFrank Piva fi 139*94c4a1e1SFrank Piva value="$(cut -d ';' -f "$field" "$FIO_OUTPUT")" 140*94c4a1e1SFrank Piva TEST_RUN["$FIO_PERF_PREFIX$name"]="$value" 141*94c4a1e1SFrank Piva done 142*94c4a1e1SFrank Piva} 143*94c4a1e1SFrank Piva 144*94c4a1e1SFrank Piva__run_fio_libaio() { 145*94c4a1e1SFrank Piva DEVS=$1 146*94c4a1e1SFrank Piva BS=$2 147*94c4a1e1SFrank Piva RW=$3 148*94c4a1e1SFrank Piva JOBS=$4 149*94c4a1e1SFrank Piva RTIME=$5 150*94c4a1e1SFrank Piva 151*94c4a1e1SFrank Piva QD=128 152*94c4a1e1SFrank Piva BATCH=16 153*94c4a1e1SFrank Piva FIO=fio 154*94c4a1e1SFrank Piva 155*94c4a1e1SFrank Piva $FIO --output=$FIO_OUTPUT --output-format=terse --terse-version=4 --group_reporting=1 \ 156*94c4a1e1SFrank Piva --bs=$BS --ioengine=libaio \ 157*94c4a1e1SFrank Piva --iodepth=$QD \ 158*94c4a1e1SFrank Piva --iodepth_batch_submit=$BATCH \ 159*94c4a1e1SFrank Piva --iodepth_batch_complete_min=$BATCH \ 160*94c4a1e1SFrank Piva --filename=$DEVS --gtod_reduce=1 \ 161*94c4a1e1SFrank Piva --direct=1 --runtime=$RTIME --numjobs=$JOBS --rw=$RW \ 162*94c4a1e1SFrank Piva --name=test > /dev/null 2>&1 163*94c4a1e1SFrank Piva} 164*94c4a1e1SFrank Piva 165*94c4a1e1SFrank Piva__ublk_loop_backing_file() { 166*94c4a1e1SFrank Piva eval $UBLK list > ${UBLK_TMP} 167*94c4a1e1SFrank Piva file=`cat ${UBLK_TMP} | grep "loop" | awk '{print $2}' | awk -F "," '{print $1}' | awk -F ":" '{print $2}'` 168*94c4a1e1SFrank Piva echo $file | xargs 169*94c4a1e1SFrank Piva} 170*94c4a1e1SFrank Piva 171*94c4a1e1SFrank Piva__ublk_dev_id() { 172*94c4a1e1SFrank Piva local dev=$1 173*94c4a1e1SFrank Piva dev_id=`echo "$dev" | awk '{print substr($1, 11)}'` 174*94c4a1e1SFrank Piva echo "$dev_id" 175*94c4a1e1SFrank Piva} 176*94c4a1e1SFrank Piva 177*94c4a1e1SFrank Piva__ublk_get_pid() { 178*94c4a1e1SFrank Piva local dev=$1 179*94c4a1e1SFrank Piva local dev_id=`__ublk_dev_id $dev` 180*94c4a1e1SFrank Piva 181*94c4a1e1SFrank Piva eval $UBLK list -n $dev_id > ${UBLK_TMP} 182*94c4a1e1SFrank Piva pid=`cat ${UBLK_TMP} | grep "pid" | awk '{print $7}'` 183*94c4a1e1SFrank Piva echo $pid 184*94c4a1e1SFrank Piva} 185*94c4a1e1SFrank Piva 186*94c4a1e1SFrank Piva__ublk_get_queue_tid() { 187*94c4a1e1SFrank Piva local dev=$1 188*94c4a1e1SFrank Piva local qid=$2 189*94c4a1e1SFrank Piva local dev_id=`__ublk_dev_id $dev` 190*94c4a1e1SFrank Piva 191*94c4a1e1SFrank Piva eval $UBLK list -n ${dev_id} > ${UBLK_TMP} 192*94c4a1e1SFrank Piva q_tid=`cat ${UBLK_TMP} | grep "queue ${qid}" | awk '{print $4}'` 193*94c4a1e1SFrank Piva echo $q_tid 194*94c4a1e1SFrank Piva} 195*94c4a1e1SFrank Piva 196*94c4a1e1SFrank Piva__ublk_get_dev_state() { 197*94c4a1e1SFrank Piva local dev=$1 198*94c4a1e1SFrank Piva local dev_id=`__ublk_dev_id $dev` 199*94c4a1e1SFrank Piva 200*94c4a1e1SFrank Piva eval $UBLK list -n ${dev_id} > ${UBLK_TMP} 201*94c4a1e1SFrank Piva state=`cat ${UBLK_TMP} | grep "state" | awk '{print $11}'` 202*94c4a1e1SFrank Piva echo $state 203*94c4a1e1SFrank Piva} 204*94c4a1e1SFrank Piva 205*94c4a1e1SFrank Piva__run_fio_perf() { 206*94c4a1e1SFrank Piva __run_fio_libaio $@ 207*94c4a1e1SFrank Piva _fio_perf_report 208*94c4a1e1SFrank Piva} 209*94c4a1e1SFrank Piva 210*94c4a1e1SFrank Piva__remove_ublk_dev_return() { 211*94c4a1e1SFrank Piva local dev="$1" 212*94c4a1e1SFrank Piva if [ "$dev" == "*" ]; then 213*94c4a1e1SFrank Piva eval $UBLK del -a 214*94c4a1e1SFrank Piva else 215*94c4a1e1SFrank Piva dev_id=`__ublk_dev_id $dev` 216*94c4a1e1SFrank Piva eval $UBLK del -n "$dev_id" 217*94c4a1e1SFrank Piva fi 218*94c4a1e1SFrank Piva RES=$? 219*94c4a1e1SFrank Piva udevadm settle 220*94c4a1e1SFrank Piva echo $RES 221*94c4a1e1SFrank Piva} 222*94c4a1e1SFrank Piva 223*94c4a1e1SFrank Piva__remove_ublk_dev() { 224*94c4a1e1SFrank Piva __remove_ublk_dev_return $@ > /dev/null 2>&1 225*94c4a1e1SFrank Piva} 226*94c4a1e1SFrank Piva 227*94c4a1e1SFrank Piva__find_free_ublk_id() 228*94c4a1e1SFrank Piva{ 229*94c4a1e1SFrank Piva for id in `seq 0 64`; do 230*94c4a1e1SFrank Piva [ -c /dev/ublkc${id} ] && continue 231*94c4a1e1SFrank Piva echo $id 232*94c4a1e1SFrank Piva break 233*94c4a1e1SFrank Piva done 234*94c4a1e1SFrank Piva [ $id == "64" ] && echo "-" 235*94c4a1e1SFrank Piva} 236*94c4a1e1SFrank Piva 237*94c4a1e1SFrank Piva__create_ublk_dev() 238*94c4a1e1SFrank Piva{ 239*94c4a1e1SFrank Piva id=`__find_free_ublk_id` 240*94c4a1e1SFrank Piva [ ${id} == "-" ] && echo "no free ublk device nodes" && exit -1 241*94c4a1e1SFrank Piva eval $UBLK add ${T_TYPE_PARAMS} -n $id > /dev/null 2>&1 242*94c4a1e1SFrank Piva udevadm settle 243*94c4a1e1SFrank Piva echo "/dev/ublkb${id}" 244*94c4a1e1SFrank Piva} 245*94c4a1e1SFrank Piva 246*94c4a1e1SFrank Piva__recover_ublk_dev() 247*94c4a1e1SFrank Piva{ 248*94c4a1e1SFrank Piva local dev=$1 249*94c4a1e1SFrank Piva local dev_id=`__ublk_dev_id $dev` 250*94c4a1e1SFrank Piva 251*94c4a1e1SFrank Piva eval $UBLK recover -n $dev_id 252*94c4a1e1SFrank Piva RES=$? 253*94c4a1e1SFrank Piva echo $RES 254*94c4a1e1SFrank Piva} 255*94c4a1e1SFrank Piva 256*94c4a1e1SFrank Piva__get_cpu_utils() 257*94c4a1e1SFrank Piva{ 258*94c4a1e1SFrank Piva local user_cpu=`echo ${TEST_RUN["user cpu"]} | awk -F "." '{print $1}'` 259*94c4a1e1SFrank Piva local sys_cpu=`echo ${TEST_RUN["system cpu"]} | awk -F "." '{print $1}'` 260*94c4a1e1SFrank Piva echo "cpu_util(${user_cpu}% ${sys_cpu}%)" 261*94c4a1e1SFrank Piva} 262*94c4a1e1SFrank Piva 263*94c4a1e1SFrank Piva__run_dev_perf_no_create() 264*94c4a1e1SFrank Piva{ 265*94c4a1e1SFrank Piva local TYPE=$1 266*94c4a1e1SFrank Piva local JOBS=$2 267*94c4a1e1SFrank Piva local DEV=$3 268*94c4a1e1SFrank Piva local RT=$TRUNTIME 269*94c4a1e1SFrank Piva local BS=4k 270*94c4a1e1SFrank Piva local FIO_PERF_FIELDS=("read iops" "write iops" "user cpu" "system cpu") 271*94c4a1e1SFrank Piva 272*94c4a1e1SFrank Piva RW="randwrite" 273*94c4a1e1SFrank Piva __run_fio_perf $DEV $BS $RW $JOBS 20 274*94c4a1e1SFrank Piva cpu_util=`__get_cpu_utils` 275*94c4a1e1SFrank Piva echo -e "\t$RW($BS): jobs $JOBS, iops ${TEST_RUN["write iops"]}, $cpu_util" 276*94c4a1e1SFrank Piva 277*94c4a1e1SFrank Piva RW="randread" 278*94c4a1e1SFrank Piva __run_fio_perf $DEV $BS $RW $JOBS $RT 279*94c4a1e1SFrank Piva cpu_util=`__get_cpu_utils` 280*94c4a1e1SFrank Piva echo -e "\t$RW($BS): jobs $JOBS, iops ${TEST_RUN["read iops"]}, $cpu_util" 281*94c4a1e1SFrank Piva 282*94c4a1e1SFrank Piva RW="randrw" 283*94c4a1e1SFrank Piva __run_fio_perf $DEV $BS $RW $JOBS $RT 284*94c4a1e1SFrank Piva cpu_util=`__get_cpu_utils` 285*94c4a1e1SFrank Piva echo -e "\t$RW($BS): jobs $JOBS, iops read ${TEST_RUN["read iops"]} write ${TEST_RUN["write iops"]}, $cpu_util" 286*94c4a1e1SFrank Piva 287*94c4a1e1SFrank Piva RW="rw" 288*94c4a1e1SFrank Piva BS=64k 289*94c4a1e1SFrank Piva __run_fio_perf $DEV $BS $RW $JOBS $RT 290*94c4a1e1SFrank Piva cpu_util=`__get_cpu_utils` 291*94c4a1e1SFrank Piva echo -e "\t$RW($BS): jobs $JOBS, iops read ${TEST_RUN["read iops"]} write ${TEST_RUN["write iops"]}, $cpu_util" 292*94c4a1e1SFrank Piva 293*94c4a1e1SFrank Piva RW="rw" 294*94c4a1e1SFrank Piva BS=512k 295*94c4a1e1SFrank Piva __run_fio_perf $DEV $BS $RW $JOBS $RT 296*94c4a1e1SFrank Piva cpu_util=`__get_cpu_utils` 297*94c4a1e1SFrank Piva echo -e "\t$RW($BS): jobs $JOBS, iops read ${TEST_RUN["read iops"]} write ${TEST_RUN["write iops"]}, $cpu_util" 298*94c4a1e1SFrank Piva 299*94c4a1e1SFrank Piva echo "" 300*94c4a1e1SFrank Piva} 301*94c4a1e1SFrank Piva 302*94c4a1e1SFrank Piva__run_dev_perf() 303*94c4a1e1SFrank Piva{ 304*94c4a1e1SFrank Piva JOBS=$1 305*94c4a1e1SFrank Piva 306*94c4a1e1SFrank Piva DEV=`__create_ublk_dev` 307*94c4a1e1SFrank Piva 308*94c4a1e1SFrank Piva echo -e "\tublk add ${T_TYPE_PARAMS}, fio: ($DEV libaio dio io jobs($JOBS))..." 309*94c4a1e1SFrank Piva __run_dev_perf_no_create "ublk" $JOBS $DEV 310*94c4a1e1SFrank Piva 311*94c4a1e1SFrank Piva __remove_ublk_dev $DEV 312*94c4a1e1SFrank Piva} 313*94c4a1e1SFrank Piva 314*94c4a1e1SFrank Piva_create_null_image() 315*94c4a1e1SFrank Piva{ 316*94c4a1e1SFrank Piva echo "" 317*94c4a1e1SFrank Piva} 318*94c4a1e1SFrank Piva 319*94c4a1e1SFrank Piva_create_image() 320*94c4a1e1SFrank Piva{ 321*94c4a1e1SFrank Piva local type=$1 322*94c4a1e1SFrank Piva 323*94c4a1e1SFrank Piva shift 1 324*94c4a1e1SFrank Piva 325*94c4a1e1SFrank Piva eval _create_${type}_image $@ 326*94c4a1e1SFrank Piva} 327*94c4a1e1SFrank Piva 328*94c4a1e1SFrank Piva_remove_null_image() 329*94c4a1e1SFrank Piva{ 330*94c4a1e1SFrank Piva echo "nothing" > /dev/null 331*94c4a1e1SFrank Piva} 332*94c4a1e1SFrank Piva 333*94c4a1e1SFrank Piva_remove_image() 334*94c4a1e1SFrank Piva{ 335*94c4a1e1SFrank Piva local type=$1 336*94c4a1e1SFrank Piva shift 1 337*94c4a1e1SFrank Piva eval _remove_${type}_image $@ 338*94c4a1e1SFrank Piva} 339