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