3 # set _FORCE_LOCAL environment variable to run blockwise unit tests even on local
4 # nfs. Some tests will fail because nfs is eager to write for example 4095 bytes
7 BW_UNIT=./unit-utils-io
10 LOCAL_FILE=./blockwise_localfile
12 # $1 path to scsi debug bdev
13 scsi_debug_teardown() {
16 while [ -b "$1" -a $_tries -gt 0 ]; do
17 rmmod scsi_debug >/dev/null 2>&1
24 test ! -b "$1" || rmmod scsi_debug >/dev/null 2>&1
28 if [ -d "$MNT_DIR" ] ; then
29 umount -f $MNT_DIR 2>/dev/null
30 rmdir $MNT_DIR 2>/dev/null
32 rm -f $LOCAL_FILE 2> /dev/null
33 scsi_debug_teardown "$DEV" || exit 100
38 if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
57 echo "TEST SKIPPED: $1"
63 rmmod scsi_debug >/dev/null 2>&1
64 if [ -d /sys/module/scsi_debug ] ; then
65 skip "Cannot use scsi_debug module (in use or compiled-in)."
67 modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
68 if [ $? -ne 0 ] ; then
69 skip "This kernel seems to not support proper scsi_debug module."
71 grep -q scsi_debug /sys/block/*/device/model || sleep 2
72 DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
74 [ -b $DEV ] || fail "Cannot find $DEV."
78 dd if=/dev/zero of=$2 bs=1M count=$1 2> /dev/null
82 for file in $(ls img_fs_*.img.xz) ; do
83 echo "Run tests in $file put on top block device."
84 xz -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
85 [ ! -d $MNT_DIR ] && mkdir $MNT_DIR
88 echo "Mounting image $file failed, skipped."
91 rm -rf $MNT_DIR/* 2>/dev/null
92 local tfile=$MNT_DIR/bwunit_tstfile
93 falloc $DEVSIZEMB $tfile || fail "enospc?"
94 local iobsize=$(stat -c "%o" $tfile)
95 test -n "$iobsize" -a $iobsize -gt 0 || fail
105 test $1 -eq 0 || truncate -c -s $1 $2 2>/dev/null || dd if=/dev/zero of=$2 bs=$1 count=1 2>/dev/null || fail "Failed to truncate test file $2."
120 _fsize=$(stat -c "%s" $_dev)
125 MSG="Testing $_fn on $_type with params $@ [expecting TRUE]..."
126 $BW_UNIT $_dev $_fn $@
127 if [ $? -ne 0 ]; then
128 if [ $_type = "file" ]; then
133 trunc_file $_fsize $_dev
134 test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-pass.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
140 MSG="Testing $_fn on $_type with params $@ [expecting FALSE]..."
141 $BW_UNIT $_dev $_fn $@ 2> /dev/null
142 if [ $? -eq 0 ]; then
143 if [ $_type = "file" ]; then
148 trunc_file $_fsize $_dev
149 test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-fail.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
155 fail "Internal test error"
159 trunc_file $_fsize $_dev
169 # buffer io support only blocksize aligned ios
170 # device/file fn_name length
171 RUN "P" $1 read_buffer $BSIZE
172 RUN "P" $1 read_buffer $((2*BSIZE))
173 RUN "F" $1 read_buffer $((BSIZE-1))
174 RUN "F" $1 read_buffer $((BSIZE+1))
175 RUN "P" $1 read_buffer 0
177 RUN "P" $1 write_buffer $BSIZE
178 RUN "P" $1 write_buffer $((2*BSIZE))
180 RUN "F" $1 write_buffer $((BSIZE-1))
181 RUN "F" $1 write_buffer $((BSIZE+1))
182 RUN "F" $1 write_buffer 0
184 # basic blockwise functions
185 # device/file fn_name length bsize
186 RUN "P" $1 read_blockwise 0 $BSIZE
187 RUN "P" $1 read_blockwise $((BSIZE)) $BSIZE
188 RUN "P" $1 read_blockwise $((BSIZE-1)) $BSIZE
189 RUN "P" $1 read_blockwise $((BSIZE+1)) $BSIZE
190 RUN "P" $1 read_blockwise $((DEVSIZE)) $BSIZE
191 RUN "P" $1 read_blockwise $((DEVSIZE-1)) $BSIZE
192 RUN "F" $1 read_blockwise $((DEVSIZE+1)) $BSIZE
194 RUN "P" $1 write_blockwise 0 $BSIZE
195 RUN "P" $1 write_blockwise $((BSIZE)) $BSIZE
196 RUN "P" $1 write_blockwise $((BSIZE-1)) $BSIZE
197 RUN "P" $1 write_blockwise $((BSIZE+1)) $BSIZE
198 RUN "P" $1 write_blockwise $((DEVSIZE)) $BSIZE
199 RUN "P" $1 write_blockwise $((DEVSIZE-1)) $BSIZE
200 RUN "$BD_FAIL" $1 write_blockwise $((DEVSIZE+1)) $BSIZE
202 # seek variant blockwise functions
203 # device/file fn_name length bsize offset
204 RUN "P" $1 read_lseek_blockwise 0 $BSIZE 0
205 RUN "P" $1 read_lseek_blockwise 0 $BSIZE 1
206 RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE))
207 # length = 0 is significant here
208 RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE+1))
210 # beginning of device
211 RUN "P" $1 read_lseek_blockwise 1 $BSIZE 0
212 RUN "P" $1 read_lseek_blockwise 1 $BSIZE 1
213 RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE-1))
214 RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE/2))
216 # somewhere in the 'middle'
217 RUN "P" $1 read_lseek_blockwise 1 $BSIZE $BSIZE
218 RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+1))
219 RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
220 RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
223 RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((BSIZE-1))
224 RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
225 RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
226 RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
227 RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
228 RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
230 # including one whole sector
231 RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
232 RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
233 RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
234 RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
235 RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
236 RUN "P" $1 read_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
238 # hiting exactly the sector boundary
239 RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE 1
240 RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
241 RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
242 RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
245 RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
246 RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
247 RUN "P" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
248 RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
250 # this must fail on both device and file
251 RUN "F" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE))
252 RUN "F" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
253 RUN "F" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
254 RUN "F" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
256 RUN "P" $1 write_lseek_blockwise 0 $BSIZE 0
257 # TODO: this may pass but must not write a byte (write(0) is undefined).
258 # Test it with underlying dm-error or phony read/write syscalls.
259 # Skipping read is optimization.
260 # HINT: currently it performs useless write and read as well
261 RUN "P" $1 write_lseek_blockwise 0 $BSIZE 1
262 RUN "P" $1 write_lseek_blockwise 0 $BSIZE $BSIZE
264 # beginning of device
265 RUN "P" $1 write_lseek_blockwise 1 $BSIZE 0
266 RUN "P" $1 write_lseek_blockwise 1 $BSIZE 1
267 RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE-1))
268 RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE/2))
270 # somewhere in the 'middle'
271 RUN "P" $1 write_lseek_blockwise 1 $BSIZE $BSIZE
272 RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+1))
273 RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
274 RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
277 RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((BSIZE-1))
278 RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
279 RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
280 RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
281 RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
282 RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
284 # including one whole sector
285 RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
286 RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
287 RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
288 RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
289 RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
290 RUN "P" $1 write_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
292 # hiting exactly the sector boundary
293 RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE 1
294 RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
295 RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
296 RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
299 RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
300 RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
301 RUN "P" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
302 RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
304 # this must fail on device, but pass on file (which is unfortunate and maybe design mistake)
305 RUN "$BD_FAIL" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE))
306 RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
307 RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
308 RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
311 command -v $STRACE >/dev/null || unset STRACE
312 test -x $BW_UNIT || skip "Run \"make `basename $BW_UNIT`\" first"
317 DEVSIZE=$((DEVSIZEMB*1024*1024))
319 PAGE_SIZE=$(getconf PAGE_SIZE)
320 echo "System PAGE_SIZE=$PAGE_SIZE"
322 echo "Run tests in local filesystem"
323 falloc $DEVSIZEMB $LOCAL_FILE || fail "Failed to create file in local filesystem."
324 BSIZE=$(stat -c "%o" $LOCAL_FILE)
325 if [ $BSIZE -gt $((512*1024)) ]; then
326 echo "Detected file block size: $BSIZE bytes"
327 echo "Tuning it down to system page size ($PAGE_SIZE bytes)"
332 [ $(id -u) -eq 0 ] || {
333 echo "WARNING: You must be root to run remaining tests."
334 test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"
344 echo "# Create classic 512B drive"
345 echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
346 add_device dev_size_mb=$DEVSIZEMB sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
349 add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
354 echo "# Create desktop-class 4K drive"
355 echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
356 add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
358 BSIZE=$((DEVBSIZE*(1<<EXP)))
362 add_device dev_size_mb=$DEVSIZEMBIMG physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
369 echo "# Create enterprise-class 4K drive"
370 echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
371 add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
374 add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
378 test $WARNS -eq 0 || echo "(WARNING: $WARNS suspicious result(s) in total)"
379 test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"