xref: /linux/tools/testing/selftests/ublk/test_common.sh (revision 6d8854216ebb60959ddb6f4ea4123bd449ba6cf6)
16aecda00SMing Lei#!/bin/bash
26aecda00SMing Lei# SPDX-License-Identifier: GPL-2.0
36aecda00SMing Lei
4c2cb669aSMing LeiUBLK_SKIP_CODE=4
5c2cb669aSMing Lei
6723977caSMing Lei_have_program() {
7723977caSMing Lei	if command -v "$1" >/dev/null 2>&1; then
8723977caSMing Lei		return 0
9723977caSMing Lei	fi
10723977caSMing Lei	return 1
11723977caSMing Lei}
12723977caSMing Lei
13723977caSMing Lei_get_disk_dev_t() {
14723977caSMing Lei	local dev_id=$1
15723977caSMing Lei	local dev
16723977caSMing Lei	local major
17723977caSMing Lei	local minor
18723977caSMing Lei
19723977caSMing Lei	dev=/dev/ublkb"${dev_id}"
201d019736SUday Shankar	major="0x"$(stat -c '%t' "$dev")
211d019736SUday Shankar	minor="0x"$(stat -c '%T' "$dev")
22723977caSMing Lei
23723977caSMing Lei	echo $(( (major & 0xfff) << 20 | (minor & 0xfffff) ))
24723977caSMing Lei}
25723977caSMing Lei
26f40b1f26SMing Lei_get_disk_size()
27f40b1f26SMing Lei{
28f40b1f26SMing Lei	lsblk -b -o SIZE -n "$1"
29f40b1f26SMing Lei}
30f40b1f26SMing Lei
318c778614SMing Lei_run_fio_verify_io() {
328c778614SMing Lei	fio --name=verify --rw=randwrite --direct=1 --ioengine=libaio \
338c778614SMing Lei		--bs=8k --iodepth=32 --verify=crc32c --do_verify=1 \
348c778614SMing Lei		--verify_state_save=0 "$@" > /dev/null
358c778614SMing Lei}
368c778614SMing Lei
375d95bfb5SMing Lei_create_backfile() {
388d31a7e5SMing Lei	local index=$1
398d31a7e5SMing Lei	local new_size=$2
408d31a7e5SMing Lei	local old_file
418d31a7e5SMing Lei	local new_file
425d95bfb5SMing Lei
438d31a7e5SMing Lei	old_file="${UBLK_BACKFILES[$index]}"
448d31a7e5SMing Lei	[ -f "$old_file" ] && rm -f "$old_file"
458d31a7e5SMing Lei
468d31a7e5SMing Lei	new_file=$(mktemp ublk_file_"${new_size}"_XXXXX)
478d31a7e5SMing Lei	truncate -s "${new_size}" "${new_file}"
488d31a7e5SMing Lei	UBLK_BACKFILES["$index"]="$new_file"
495d95bfb5SMing Lei}
505d95bfb5SMing Lei
518d31a7e5SMing Lei_remove_files() {
528d31a7e5SMing Lei	local file
535d95bfb5SMing Lei
548d31a7e5SMing Lei	for file in "${UBLK_BACKFILES[@]}"; do
55632051ffSMing Lei		[ -f "$file" ] && rm -f "$file"
568d31a7e5SMing Lei	done
578d31a7e5SMing Lei	[ -f "$UBLK_TMP" ] && rm -f "$UBLK_TMP"
585d95bfb5SMing Lei}
595d95bfb5SMing Lei
605d95bfb5SMing Lei_create_tmp_dir() {
61632051ffSMing Lei	local my_file;
625d95bfb5SMing Lei
63632051ffSMing Lei	my_file=$(mktemp -d ublk_dir_XXXXX)
64632051ffSMing Lei	echo "$my_file"
655d95bfb5SMing Lei}
665d95bfb5SMing Lei
675d95bfb5SMing Lei_remove_tmp_dir() {
685d95bfb5SMing Lei	local dir=$1
695d95bfb5SMing Lei
70632051ffSMing Lei	[ -d "$dir" ] && rmdir "$dir"
715d95bfb5SMing Lei}
725d95bfb5SMing Lei
735d95bfb5SMing Lei_mkfs_mount_test()
745d95bfb5SMing Lei{
755d95bfb5SMing Lei	local dev=$1
765d95bfb5SMing Lei	local err_code=0
77632051ffSMing Lei	local mnt_dir;
785d95bfb5SMing Lei
79632051ffSMing Lei	mnt_dir=$(_create_tmp_dir)
80632051ffSMing Lei	mkfs.ext4 -F "$dev" > /dev/null 2>&1
815d95bfb5SMing Lei	err_code=$?
825d95bfb5SMing Lei	if [ $err_code -ne 0 ]; then
835d95bfb5SMing Lei		return $err_code
845d95bfb5SMing Lei	fi
855d95bfb5SMing Lei
86632051ffSMing Lei	mount -t ext4 "$dev" "$mnt_dir" > /dev/null 2>&1
87632051ffSMing Lei	umount "$dev"
885d95bfb5SMing Lei	err_code=$?
89632051ffSMing Lei	_remove_tmp_dir "$mnt_dir"
905d95bfb5SMing Lei	if [ $err_code -ne 0 ]; then
915d95bfb5SMing Lei		return $err_code
925d95bfb5SMing Lei	fi
935d95bfb5SMing Lei}
945d95bfb5SMing Lei
956aecda00SMing Lei_check_root() {
966aecda00SMing Lei	local ksft_skip=4
976aecda00SMing Lei
986aecda00SMing Lei	if [ $UID != 0 ]; then
996aecda00SMing Lei		echo please run this as root >&2
1006aecda00SMing Lei		exit $ksft_skip
1016aecda00SMing Lei	fi
1026aecda00SMing Lei}
1036aecda00SMing Lei
1046aecda00SMing Lei_remove_ublk_devices() {
1056aecda00SMing Lei	${UBLK_PROG} del -a
106fe2230d9SMing Lei	modprobe -r ublk_drv > /dev/null 2>&1
1076aecda00SMing Lei}
1086aecda00SMing Lei
1096aecda00SMing Lei_get_ublk_dev_state() {
1106aecda00SMing Lei	${UBLK_PROG} list -n "$1" | grep "state" | awk '{print $11}'
1116aecda00SMing Lei}
1126aecda00SMing Lei
1136aecda00SMing Lei_get_ublk_daemon_pid() {
1146aecda00SMing Lei	${UBLK_PROG} list -n "$1" | grep "pid" | awk '{print $7}'
1156aecda00SMing Lei}
1166aecda00SMing Lei
1176aecda00SMing Lei_prep_test() {
1186aecda00SMing Lei	_check_root
1196aecda00SMing Lei	local type=$1
1206aecda00SMing Lei	shift 1
121fe2230d9SMing Lei	modprobe ublk_drv > /dev/null 2>&1
1223bf54060SMing Lei	UBLK_TMP=$(mktemp ublk_test_XXXXX)
123390174c9SMing Lei	[ "$UBLK_TEST_QUIET" -eq 0 ] && echo "ublk $type: $*"
1246aecda00SMing Lei}
1256aecda00SMing Lei
126c2cb669aSMing Lei_remove_test_files()
127c2cb669aSMing Lei{
128c2cb669aSMing Lei	local files=$*
129c2cb669aSMing Lei
130c2cb669aSMing Lei	for file in ${files}; do
131c2cb669aSMing Lei		[ -f "${file}" ] && rm -f "${file}"
132c2cb669aSMing Lei	done
133c2cb669aSMing Lei}
134c2cb669aSMing Lei
1356aecda00SMing Lei_show_result()
1366aecda00SMing Lei{
137beb31982SMing Lei	if [ "$UBLK_TEST_SHOW_RESULT" -ne 0 ]; then
138c2cb669aSMing Lei		if [ "$2" -eq 0 ]; then
1396aecda00SMing Lei			echo "$1 : [PASS]"
140c2cb669aSMing Lei		elif [ "$2" -eq 4 ]; then
141c2cb669aSMing Lei			echo "$1 : [SKIP]"
142c2cb669aSMing Lei		else
143c2cb669aSMing Lei			echo "$1 : [FAIL]"
144c2cb669aSMing Lei		fi
145beb31982SMing Lei	fi
1468d31a7e5SMing Lei	if [ "$2" -ne 0 ]; then
1478d31a7e5SMing Lei		_remove_files
1488d31a7e5SMing Lei		exit "$2"
1498d31a7e5SMing Lei	fi
150c2cb669aSMing Lei	return 0
151c2cb669aSMing Lei}
152c2cb669aSMing Lei
153c2cb669aSMing Lei# don't call from sub-shell, otherwise can't exit
154c2cb669aSMing Lei_check_add_dev()
155c2cb669aSMing Lei{
156c2cb669aSMing Lei	local tid=$1
157c2cb669aSMing Lei	local code=$2
1588d31a7e5SMing Lei
159c2cb669aSMing Lei	if [ "${code}" -ne 0 ]; then
160c2cb669aSMing Lei		_show_result "${tid}" "${code}"
1616aecda00SMing Lei	fi
1626aecda00SMing Lei}
1636aecda00SMing Lei
1646aecda00SMing Lei_cleanup_test() {
165c83b089aSMing Lei	"${UBLK_PROG}" del -a
1668d31a7e5SMing Lei
1678d31a7e5SMing Lei	_remove_files
1686aecda00SMing Lei}
1696aecda00SMing Lei
170c2cb669aSMing Lei_have_feature()
171c2cb669aSMing Lei{
172c2cb669aSMing Lei	if  $UBLK_PROG "features" | grep "$1" > /dev/null 2>&1; then
173c2cb669aSMing Lei		return 0
174c2cb669aSMing Lei	fi
175c2cb669aSMing Lei	return 1
176c2cb669aSMing Lei}
177c2cb669aSMing Lei
17857e13a2eSMing Lei_create_ublk_dev() {
179632051ffSMing Lei	local dev_id;
18057e13a2eSMing Lei	local cmd=$1
18157e13a2eSMing Lei
18257e13a2eSMing Lei	shift 1
183632051ffSMing Lei
18487a92652SMing Lei	if [ ! -c /dev/ublk-control ]; then
18587a92652SMing Lei		return ${UBLK_SKIP_CODE}
18687a92652SMing Lei	fi
187c2cb669aSMing Lei	if echo "$@" | grep -q "\-z"; then
188c2cb669aSMing Lei		if ! _have_feature "ZERO_COPY"; then
189c2cb669aSMing Lei			return ${UBLK_SKIP_CODE}
190c2cb669aSMing Lei		fi
191c2cb669aSMing Lei	fi
192c2cb669aSMing Lei
19357e13a2eSMing Lei	if ! dev_id=$("${UBLK_PROG}" "$cmd" "$@" | grep "dev id" | awk -F '[ :]' '{print $3}'); then
194632051ffSMing Lei		echo "fail to add ublk dev $*"
195632051ffSMing Lei		return 255
1966aecda00SMing Lei	fi
1976aecda00SMing Lei	udevadm settle
198573840abSMing Lei
199573840abSMing Lei	if [[ "$dev_id" =~ ^[0-9]+$ ]]; then
200632051ffSMing Lei		echo "${dev_id}"
201573840abSMing Lei	else
202573840abSMing Lei		return 255
203573840abSMing Lei	fi
2046aecda00SMing Lei}
2056aecda00SMing Lei
20657e13a2eSMing Lei_add_ublk_dev() {
20757e13a2eSMing Lei	_create_ublk_dev "add" "$@"
20857e13a2eSMing Lei}
20957e13a2eSMing Lei
21057e13a2eSMing Lei_recover_ublk_dev() {
21157e13a2eSMing Lei	local dev_id
21257e13a2eSMing Lei	local state
21357e13a2eSMing Lei
21457e13a2eSMing Lei	dev_id=$(_create_ublk_dev "recover" "$@")
21557e13a2eSMing Lei	for ((j=0;j<20;j++)); do
21657e13a2eSMing Lei		state=$(_get_ublk_dev_state "${dev_id}")
21757e13a2eSMing Lei		[ "$state" == "LIVE" ] && break
21857e13a2eSMing Lei		sleep 1
21957e13a2eSMing Lei	done
22057e13a2eSMing Lei	echo "$state"
22157e13a2eSMing Lei}
22257e13a2eSMing Lei
223533c87e2SMing Lei# quiesce device and return ublk device state
224533c87e2SMing Lei__ublk_quiesce_dev()
225533c87e2SMing Lei{
226533c87e2SMing Lei	local dev_id=$1
227533c87e2SMing Lei	local exp_state=$2
228533c87e2SMing Lei	local state
229533c87e2SMing Lei
230533c87e2SMing Lei	if ! ${UBLK_PROG} quiesce -n "${dev_id}"; then
231533c87e2SMing Lei		state=$(_get_ublk_dev_state "${dev_id}")
232533c87e2SMing Lei		return "$state"
233533c87e2SMing Lei	fi
234533c87e2SMing Lei
235533c87e2SMing Lei	for ((j=0;j<50;j++)); do
236533c87e2SMing Lei		state=$(_get_ublk_dev_state "${dev_id}")
237533c87e2SMing Lei		[ "$state" == "$exp_state" ] && break
238533c87e2SMing Lei		sleep 1
239533c87e2SMing Lei	done
240533c87e2SMing Lei	echo "$state"
241533c87e2SMing Lei}
242533c87e2SMing Lei
243af83ccc7SMing Lei# kill the ublk daemon and return ublk device state
244af83ccc7SMing Lei__ublk_kill_daemon()
245af83ccc7SMing Lei{
246af83ccc7SMing Lei	local dev_id=$1
247af83ccc7SMing Lei	local exp_state=$2
248af83ccc7SMing Lei	local daemon_pid
249af83ccc7SMing Lei	local state
250af83ccc7SMing Lei
251af83ccc7SMing Lei	daemon_pid=$(_get_ublk_daemon_pid "${dev_id}")
252af83ccc7SMing Lei	state=$(_get_ublk_dev_state "${dev_id}")
253af83ccc7SMing Lei
254af83ccc7SMing Lei	for ((j=0;j<50;j++)); do
255af83ccc7SMing Lei		[ "$state" == "$exp_state" ] && break
256af83ccc7SMing Lei		kill -9 "$daemon_pid" > /dev/null 2>&1
257af83ccc7SMing Lei		sleep 1
258af83ccc7SMing Lei		state=$(_get_ublk_dev_state "${dev_id}")
259af83ccc7SMing Lei	done
260af83ccc7SMing Lei	echo "$state"
261af83ccc7SMing Lei}
262af83ccc7SMing Lei
263c60ac48eSMing Lei__remove_ublk_dev_return() {
264c60ac48eSMing Lei	local dev_id=$1
265c60ac48eSMing Lei
266c60ac48eSMing Lei	${UBLK_PROG} del -n "${dev_id}"
267c60ac48eSMing Lei	local res=$?
268c60ac48eSMing Lei	udevadm settle
269c60ac48eSMing Lei	return ${res}
270c60ac48eSMing Lei}
271c60ac48eSMing Lei
272c60ac48eSMing Lei__run_io_and_remove()
273c60ac48eSMing Lei{
274c60ac48eSMing Lei	local dev_id=$1
275c60ac48eSMing Lei	local size=$2
276af83ccc7SMing Lei	local kill_server=$3
277c60ac48eSMing Lei
278c60ac48eSMing Lei	fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio \
2793fee1257SMing Lei		--rw=randrw --norandommap --iodepth=256 --size="${size}" --numjobs="$(nproc)" \
280c60ac48eSMing Lei		--runtime=20 --time_based > /dev/null 2>&1 &
281*17574aa2SUday Shankar	fio --name=batchjob --filename=/dev/ublkb"${dev_id}" --ioengine=io_uring \
282*17574aa2SUday Shankar		--rw=randrw --norandommap --iodepth=256 --size="${size}" \
283*17574aa2SUday Shankar		--numjobs="$(nproc)" --runtime=20 --time_based \
284*17574aa2SUday Shankar		--iodepth_batch_submit=32 --iodepth_batch_complete_min=32 \
285*17574aa2SUday Shankar		--force_async=7 > /dev/null 2>&1 &
286c60ac48eSMing Lei	sleep 2
287af83ccc7SMing Lei	if [ "${kill_server}" = "yes" ]; then
288af83ccc7SMing Lei		local state
289af83ccc7SMing Lei		state=$(__ublk_kill_daemon "${dev_id}" "DEAD")
290af83ccc7SMing Lei		if [ "$state" != "DEAD" ]; then
291af83ccc7SMing Lei			echo "device isn't dead($state) after killing daemon"
292af83ccc7SMing Lei			return 255
293af83ccc7SMing Lei		fi
294af83ccc7SMing Lei	fi
295c60ac48eSMing Lei	if ! __remove_ublk_dev_return "${dev_id}"; then
296c60ac48eSMing Lei		echo "delete dev ${dev_id} failed"
297c60ac48eSMing Lei		return 255
298c60ac48eSMing Lei	fi
299c60ac48eSMing Lei	wait
300c60ac48eSMing Lei}
301c60ac48eSMing Lei
302bb2cabf2SMing Leirun_io_and_remove()
303bb2cabf2SMing Lei{
304bb2cabf2SMing Lei	local size=$1
305bb2cabf2SMing Lei	local dev_id
306bb2cabf2SMing Lei	shift 1
307bb2cabf2SMing Lei
308bb2cabf2SMing Lei	dev_id=$(_add_ublk_dev "$@")
309bb2cabf2SMing Lei	_check_add_dev "$TID" $?
310bb2cabf2SMing Lei
311bb2cabf2SMing Lei	[ "$UBLK_TEST_QUIET" -eq 0 ] && echo "run ublk IO vs. remove device(ublk add $*)"
312bb2cabf2SMing Lei	if ! __run_io_and_remove "$dev_id" "${size}" "no"; then
313bb2cabf2SMing Lei		echo "/dev/ublkc$dev_id isn't removed"
314bb2cabf2SMing Lei		exit 255
315bb2cabf2SMing Lei	fi
316bb2cabf2SMing Lei}
317bb2cabf2SMing Lei
318bb2cabf2SMing Leirun_io_and_kill_daemon()
319bb2cabf2SMing Lei{
320bb2cabf2SMing Lei	local size=$1
321bb2cabf2SMing Lei	local dev_id
322bb2cabf2SMing Lei	shift 1
323bb2cabf2SMing Lei
324bb2cabf2SMing Lei	dev_id=$(_add_ublk_dev "$@")
325bb2cabf2SMing Lei	_check_add_dev "$TID" $?
326bb2cabf2SMing Lei
327bb2cabf2SMing Lei	[ "$UBLK_TEST_QUIET" -eq 0 ] && echo "run ublk IO vs kill ublk server(ublk add $*)"
328bb2cabf2SMing Lei	if ! __run_io_and_remove "$dev_id" "${size}" "yes"; then
329bb2cabf2SMing Lei		echo "/dev/ublkc$dev_id isn't removed res ${res}"
330bb2cabf2SMing Lei		exit 255
331bb2cabf2SMing Lei	fi
332bb2cabf2SMing Lei}
333bb2cabf2SMing Lei
33457e13a2eSMing Leirun_io_and_recover()
33557e13a2eSMing Lei{
336533c87e2SMing Lei	local action=$1
33757e13a2eSMing Lei	local state
33857e13a2eSMing Lei	local dev_id
33957e13a2eSMing Lei
340533c87e2SMing Lei	shift 1
34157e13a2eSMing Lei	dev_id=$(_add_ublk_dev "$@")
34257e13a2eSMing Lei	_check_add_dev "$TID" $?
34357e13a2eSMing Lei
34457e13a2eSMing Lei	fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio \
345533c87e2SMing Lei		--rw=randread --iodepth=256 --size="${size}" --numjobs=4 \
34657e13a2eSMing Lei		--runtime=20 --time_based > /dev/null 2>&1 &
34757e13a2eSMing Lei	sleep 4
34857e13a2eSMing Lei
349533c87e2SMing Lei	if [ "$action" == "kill_daemon" ]; then
35057e13a2eSMing Lei		state=$(__ublk_kill_daemon "${dev_id}" "QUIESCED")
351533c87e2SMing Lei	elif [ "$action" == "quiesce_dev" ]; then
352533c87e2SMing Lei		state=$(__ublk_quiesce_dev "${dev_id}" "QUIESCED")
353533c87e2SMing Lei	fi
35457e13a2eSMing Lei	if [ "$state" != "QUIESCED" ]; then
355533c87e2SMing Lei		echo "device isn't quiesced($state) after $action"
35657e13a2eSMing Lei		return 255
35757e13a2eSMing Lei	fi
35857e13a2eSMing Lei
35957e13a2eSMing Lei	state=$(_recover_ublk_dev -n "$dev_id" "$@")
36057e13a2eSMing Lei	if [ "$state" != "LIVE" ]; then
36157e13a2eSMing Lei		echo "faile to recover to LIVE($state)"
36257e13a2eSMing Lei		return 255
36357e13a2eSMing Lei	fi
36457e13a2eSMing Lei
36557e13a2eSMing Lei	if ! __remove_ublk_dev_return "${dev_id}"; then
36657e13a2eSMing Lei		echo "delete dev ${dev_id} failed"
36757e13a2eSMing Lei		return 255
36857e13a2eSMing Lei	fi
36957e13a2eSMing Lei	wait
37057e13a2eSMing Lei}
37157e13a2eSMing Lei
37257e13a2eSMing Lei
373390174c9SMing Lei_ublk_test_top_dir()
374390174c9SMing Lei{
375390174c9SMing Lei	cd "$(dirname "$0")" && pwd
376390174c9SMing Lei}
377c60ac48eSMing Lei
378390174c9SMing LeiUBLK_PROG=$(_ublk_test_top_dir)/kublk
379390174c9SMing LeiUBLK_TEST_QUIET=1
380beb31982SMing LeiUBLK_TEST_SHOW_RESULT=1
3818d31a7e5SMing LeiUBLK_BACKFILES=()
382632051ffSMing Leiexport UBLK_PROG
383390174c9SMing Leiexport UBLK_TEST_QUIET
384beb31982SMing Leiexport UBLK_TEST_SHOW_RESULT
385