xref: /spdk/scripts/fio-wrapper (revision a6dbe3721eb3b5990707fc3e378c95e505dd8ab5)
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