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