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