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