xref: /linux/tools/testing/selftests/ublk/test_common.sh (revision e31fd36da9c41f9f664e51a35860e9f606e81ef4)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4UBLK_SKIP_CODE=4
5
6_have_program() {
7	if command -v "$1" >/dev/null 2>&1; then
8		return 0
9	fi
10	return 1
11}
12
13_get_disk_dev_t() {
14	local dev_id=$1
15	local dev
16	local major
17	local minor
18
19	dev=/dev/ublkb"${dev_id}"
20	major=$(stat -c '%Hr' "$dev")
21	minor=$(stat -c '%Lr' "$dev")
22
23	echo $(( (major & 0xfff) << 20 | (minor & 0xfffff) ))
24}
25
26_run_fio_verify_io() {
27	fio --name=verify --rw=randwrite --direct=1 --ioengine=libaio \
28		--bs=8k --iodepth=32 --verify=crc32c --do_verify=1 \
29		--verify_state_save=0 "$@" > /dev/null
30}
31
32_create_backfile() {
33	local my_size=$1
34	local my_file
35
36	my_file=$(mktemp ublk_file_"${my_size}"_XXXXX)
37	truncate -s "${my_size}" "${my_file}"
38	echo "$my_file"
39}
40
41_remove_backfile() {
42	local file=$1
43
44	[ -f "$file" ] && rm -f "$file"
45}
46
47_create_tmp_dir() {
48	local my_file;
49
50	my_file=$(mktemp -d ublk_dir_XXXXX)
51	echo "$my_file"
52}
53
54_remove_tmp_dir() {
55	local dir=$1
56
57	[ -d "$dir" ] && rmdir "$dir"
58}
59
60_mkfs_mount_test()
61{
62	local dev=$1
63	local err_code=0
64	local mnt_dir;
65
66	mnt_dir=$(_create_tmp_dir)
67	mkfs.ext4 -F "$dev" > /dev/null 2>&1
68	err_code=$?
69	if [ $err_code -ne 0 ]; then
70		return $err_code
71	fi
72
73	mount -t ext4 "$dev" "$mnt_dir" > /dev/null 2>&1
74	umount "$dev"
75	err_code=$?
76	_remove_tmp_dir "$mnt_dir"
77	if [ $err_code -ne 0 ]; then
78		return $err_code
79	fi
80}
81
82_check_root() {
83	local ksft_skip=4
84
85	if [ $UID != 0 ]; then
86		echo please run this as root >&2
87		exit $ksft_skip
88	fi
89}
90
91_remove_ublk_devices() {
92	${UBLK_PROG} del -a
93	modprobe -r ublk_drv > /dev/null 2>&1
94}
95
96_get_ublk_dev_state() {
97	${UBLK_PROG} list -n "$1" | grep "state" | awk '{print $11}'
98}
99
100_get_ublk_daemon_pid() {
101	${UBLK_PROG} list -n "$1" | grep "pid" | awk '{print $7}'
102}
103
104_prep_test() {
105	_check_root
106	local type=$1
107	shift 1
108	modprobe ublk_drv > /dev/null 2>&1
109	[ "$UBLK_TEST_QUIET" -eq 0 ] && echo "ublk $type: $*"
110}
111
112_remove_test_files()
113{
114	local files=$*
115
116	for file in ${files}; do
117		[ -f "${file}" ] && rm -f "${file}"
118	done
119}
120
121_show_result()
122{
123	if [ "$UBLK_TEST_SHOW_RESULT" -ne 0 ]; then
124		if [ "$2" -eq 0 ]; then
125			echo "$1 : [PASS]"
126		elif [ "$2" -eq 4 ]; then
127			echo "$1 : [SKIP]"
128		else
129			echo "$1 : [FAIL]"
130		fi
131	fi
132	[ "$2" -ne 0 ] && exit "$2"
133	return 0
134}
135
136# don't call from sub-shell, otherwise can't exit
137_check_add_dev()
138{
139	local tid=$1
140	local code=$2
141	shift 2
142	if [ "${code}" -ne 0 ]; then
143		_remove_test_files "$@"
144		_show_result "${tid}" "${code}"
145	fi
146}
147
148_cleanup_test() {
149	"${UBLK_PROG}" del -a
150	rm -f "$UBLK_TMP"
151}
152
153_have_feature()
154{
155	if  $UBLK_PROG "features" | grep "$1" > /dev/null 2>&1; then
156		return 0
157	fi
158	return 1
159}
160
161_add_ublk_dev() {
162	local kublk_temp;
163	local dev_id;
164
165	if [ ! -c /dev/ublk-control ]; then
166		return ${UBLK_SKIP_CODE}
167	fi
168	if echo "$@" | grep -q "\-z"; then
169		if ! _have_feature "ZERO_COPY"; then
170			return ${UBLK_SKIP_CODE}
171		fi
172	fi
173
174	kublk_temp=$(mktemp /tmp/kublk-XXXXXX)
175	if ! "${UBLK_PROG}" add "$@" > "${kublk_temp}" 2>&1; then
176		echo "fail to add ublk dev $*"
177		rm -f "${kublk_temp}"
178		return 255
179	fi
180
181	dev_id=$(grep "dev id" "${kublk_temp}" | awk -F '[ :]' '{print $3}')
182	udevadm settle
183	rm -f "${kublk_temp}"
184	echo "${dev_id}"
185}
186
187# kill the ublk daemon and return ublk device state
188__ublk_kill_daemon()
189{
190	local dev_id=$1
191	local exp_state=$2
192	local daemon_pid
193	local state
194
195	daemon_pid=$(_get_ublk_daemon_pid "${dev_id}")
196	state=$(_get_ublk_dev_state "${dev_id}")
197
198	for ((j=0;j<50;j++)); do
199		[ "$state" == "$exp_state" ] && break
200		kill -9 "$daemon_pid" > /dev/null 2>&1
201		sleep 1
202		state=$(_get_ublk_dev_state "${dev_id}")
203	done
204	echo "$state"
205}
206
207__remove_ublk_dev_return() {
208	local dev_id=$1
209
210	${UBLK_PROG} del -n "${dev_id}"
211	local res=$?
212	udevadm settle
213	return ${res}
214}
215
216__run_io_and_remove()
217{
218	local dev_id=$1
219	local size=$2
220	local kill_server=$3
221
222	fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio \
223		--rw=readwrite --iodepth=64 --size="${size}" --numjobs=4 \
224		--runtime=20 --time_based > /dev/null 2>&1 &
225	sleep 2
226	if [ "${kill_server}" = "yes" ]; then
227		local state
228		state=$(__ublk_kill_daemon "${dev_id}" "DEAD")
229		if [ "$state" != "DEAD" ]; then
230			echo "device isn't dead($state) after killing daemon"
231			return 255
232		fi
233	fi
234	if ! __remove_ublk_dev_return "${dev_id}"; then
235		echo "delete dev ${dev_id} failed"
236		return 255
237	fi
238	wait
239}
240
241_ublk_test_top_dir()
242{
243	cd "$(dirname "$0")" && pwd
244}
245
246UBLK_TMP=$(mktemp ublk_test_XXXXX)
247UBLK_PROG=$(_ublk_test_top_dir)/kublk
248UBLK_TEST_QUIET=1
249UBLK_TEST_SHOW_RESULT=1
250export UBLK_PROG
251export UBLK_TEST_QUIET
252export UBLK_TEST_SHOW_RESULT
253