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