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