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