mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
If bash test script uses a pattern that test that command should fail command && fail (IOW fail function is called only if command exited successfully), it can mask potential segfault, as it return non-zero exit code. Fix it by using trap for scripts that uses this pattern. The same applies for SIGABRT (abort() call).
384 lines
12 KiB
Bash
Executable File
384 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# set _FORCE_LOCAL environment variable to run blockwise unit tests even on local
|
|
# nfs. Some tests will fail because nfs is eager to write for example 4095 bytes
|
|
# in O_DIRECT mode.
|
|
|
|
BW_UNIT=./unit-utils-io
|
|
STRACE=strace
|
|
MNT_DIR=./mnt_bwunit
|
|
LOCAL_FILE=./blockwise_localfile
|
|
|
|
# $1 path to scsi debug bdev
|
|
scsi_debug_teardown() {
|
|
local _tries=15;
|
|
|
|
while [ -b "$1" -a $_tries -gt 0 ]; do
|
|
rmmod scsi_debug >/dev/null 2>&1
|
|
if [ -b "$1" ]; then
|
|
sleep .1
|
|
_tries=$((_tries-1))
|
|
fi
|
|
done
|
|
|
|
test ! -b "$1" || rmmod scsi_debug >/dev/null 2>&1
|
|
}
|
|
|
|
cleanup() {
|
|
if [ -d "$MNT_DIR" ] ; then
|
|
umount -f $MNT_DIR 2>/dev/null
|
|
rmdir $MNT_DIR 2>/dev/null
|
|
fi
|
|
rm -f $LOCAL_FILE 2> /dev/null
|
|
scsi_debug_teardown "$DEV" || exit 100
|
|
}
|
|
|
|
fail()
|
|
{
|
|
if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
|
|
cleanup
|
|
exit 100
|
|
}
|
|
|
|
_sigchld() { local c=$?; [ $c -eq 139 ] && fail "Segfault"; [ $c -eq 134 ] && fail "Aborted"; }
|
|
trap _sigchld CHLD
|
|
|
|
fail_count()
|
|
{
|
|
echo "$MSG[FAIL]"
|
|
FAILS=$((FAILS+1))
|
|
}
|
|
|
|
warn_count()
|
|
{
|
|
echo "$MSG[WARNING]"
|
|
WARNS=$((WARNS+1))
|
|
}
|
|
|
|
skip()
|
|
{
|
|
echo "TEST SKIPPED: $1"
|
|
cleanup
|
|
exit 77
|
|
}
|
|
|
|
add_device() {
|
|
rmmod scsi_debug >/dev/null 2>&1
|
|
if [ -d /sys/module/scsi_debug ] ; then
|
|
skip "Cannot use scsi_debug module (in use or compiled-in)."
|
|
fi
|
|
modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
|
|
if [ $? -ne 0 ] ; then
|
|
skip "This kernel seems to not support proper scsi_debug module."
|
|
fi
|
|
sleep 1
|
|
DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
|
|
DEV="/dev/$DEV"
|
|
[ -b $DEV ] || fail "Cannot find $DEV."
|
|
}
|
|
|
|
falloc() {
|
|
dd if=/dev/zero of=$2 bs=1M count=$1 2> /dev/null
|
|
}
|
|
|
|
run_all_in_fs() {
|
|
for file in $(ls img_fs_*.img.xz) ; do
|
|
echo -n "Run tests in $file put on top block device. "
|
|
xz -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
|
|
[ ! -d $MNT_DIR ] && mkdir $MNT_DIR
|
|
mount $DEV $MNT_DIR 2>/dev/null
|
|
if [ $? -ne 0 ]; then
|
|
echo "[N/A]"
|
|
continue;
|
|
fi
|
|
rm -rf $MNT_DIR/* 2>/dev/null
|
|
local tfile=$MNT_DIR/bwunit_tstfile
|
|
falloc $DEVSIZEMB $tfile || fail "enospc?"
|
|
local iobsize=$(stat -c "%o" $tfile)
|
|
test -n "$iobsize" -a $iobsize -gt 0 || fail
|
|
local oldbsize=$BSIZE
|
|
BSIZE=$iobsize
|
|
run_all $tfile
|
|
BSIZE=$oldbsize
|
|
umount $MNT_DIR || fail
|
|
echo "[OK]"
|
|
done
|
|
}
|
|
|
|
trunc_file() {
|
|
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."
|
|
}
|
|
|
|
RUN() {
|
|
local _res=$1
|
|
shift
|
|
local _dev=$1
|
|
shift
|
|
local _fn=$1
|
|
shift
|
|
local _type="bdev"
|
|
local _fsize=0
|
|
|
|
test -b $_dev || {
|
|
_type="file"
|
|
_fsize=$(stat -c "%s" $_dev)
|
|
}
|
|
|
|
case "$_res" in
|
|
P)
|
|
MSG="Testing $_fn on $_type with params $@ [expecting TRUE]..."
|
|
$BW_UNIT $_dev $_fn $@
|
|
if [ $? -ne 0 ]; then
|
|
if [ $_type = "file" ]; then
|
|
warn_count
|
|
else
|
|
fail_count
|
|
fi
|
|
trunc_file $_fsize $_dev
|
|
test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-pass.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
|
|
else
|
|
MSG="$MSG[OK]"
|
|
fi
|
|
;;
|
|
F)
|
|
MSG="Testing $_fn on $_type with params $@ [expecting FALSE]..."
|
|
$BW_UNIT $_dev $_fn $@ 2> /dev/null
|
|
if [ $? -eq 0 ]; then
|
|
if [ $_type = "file" ]; then
|
|
warn_count
|
|
else
|
|
fail_count
|
|
fi
|
|
trunc_file $_fsize $_dev
|
|
test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-fail.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
|
|
else
|
|
MSG="$MSG[OK]"
|
|
fi
|
|
;;
|
|
*)
|
|
fail "Internal test error"
|
|
;;
|
|
esac
|
|
|
|
trunc_file $_fsize $_dev
|
|
}
|
|
|
|
run_all() {
|
|
if [ -b "$1" ]; then
|
|
BD_FAIL="F"
|
|
else
|
|
BD_FAIL="P"
|
|
fi
|
|
|
|
# buffer io support only blocksize aligned ios
|
|
# device/file fn_name length
|
|
RUN "P" $1 read_buffer $BSIZE
|
|
RUN "P" $1 read_buffer $((2*BSIZE))
|
|
RUN "F" $1 read_buffer $((BSIZE-1))
|
|
RUN "F" $1 read_buffer $((BSIZE+1))
|
|
RUN "P" $1 read_buffer 0
|
|
|
|
RUN "P" $1 write_buffer $BSIZE
|
|
RUN "P" $1 write_buffer $((2*BSIZE))
|
|
|
|
RUN "F" $1 write_buffer $((BSIZE-1))
|
|
RUN "F" $1 write_buffer $((BSIZE+1))
|
|
RUN "F" $1 write_buffer 0
|
|
|
|
# basic blockwise functions
|
|
# device/file fn_name length bsize
|
|
RUN "P" $1 read_blockwise 0 $BSIZE
|
|
RUN "P" $1 read_blockwise $((BSIZE)) $BSIZE
|
|
RUN "P" $1 read_blockwise $((BSIZE-1)) $BSIZE
|
|
RUN "P" $1 read_blockwise $((BSIZE+1)) $BSIZE
|
|
RUN "P" $1 read_blockwise $((DEVSIZE)) $BSIZE
|
|
RUN "P" $1 read_blockwise $((DEVSIZE-1)) $BSIZE
|
|
RUN "F" $1 read_blockwise $((DEVSIZE+1)) $BSIZE
|
|
|
|
RUN "P" $1 write_blockwise 0 $BSIZE
|
|
RUN "P" $1 write_blockwise $((BSIZE)) $BSIZE
|
|
RUN "P" $1 write_blockwise $((BSIZE-1)) $BSIZE
|
|
RUN "P" $1 write_blockwise $((BSIZE+1)) $BSIZE
|
|
RUN "P" $1 write_blockwise $((DEVSIZE)) $BSIZE
|
|
RUN "P" $1 write_blockwise $((DEVSIZE-1)) $BSIZE
|
|
RUN "$BD_FAIL" $1 write_blockwise $((DEVSIZE+1)) $BSIZE
|
|
|
|
# seek variant blockwise functions
|
|
# device/file fn_name length bsize offset
|
|
RUN "P" $1 read_lseek_blockwise 0 $BSIZE 0
|
|
RUN "P" $1 read_lseek_blockwise 0 $BSIZE 1
|
|
RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE))
|
|
# length = 0 is significant here
|
|
RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE+1))
|
|
|
|
# beginning of device
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE 0
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE 1
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE/2))
|
|
|
|
# somewhere in the 'middle'
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE $BSIZE
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
|
|
|
|
# cross-sector tests
|
|
RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
|
|
|
|
# including one whole sector
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
|
|
RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 read_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
|
|
|
|
# hitting exactly the sector boundary
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE 1
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
|
|
|
|
# device end
|
|
RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
|
|
RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
|
|
|
|
# this must fail on both device and file
|
|
RUN "F" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE))
|
|
RUN "F" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
|
|
RUN "F" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
|
|
RUN "F" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
|
|
|
|
RUN "P" $1 write_lseek_blockwise 0 $BSIZE 0
|
|
# TODO: this may pass but must not write a byte (write(0) is undefined).
|
|
# Test it with underlying dm-error or phony read/write syscalls.
|
|
# Skipping read is optimization.
|
|
# HINT: currently it performs useless write and read as well
|
|
RUN "P" $1 write_lseek_blockwise 0 $BSIZE 1
|
|
RUN "P" $1 write_lseek_blockwise 0 $BSIZE $BSIZE
|
|
|
|
# beginning of device
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE 0
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE 1
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE/2))
|
|
|
|
# somewhere in the 'middle'
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE $BSIZE
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
|
|
|
|
# cross-sector tests
|
|
RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
|
|
|
|
# including one whole sector
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
|
|
RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 write_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
|
|
|
|
# hitting exactly the sector boundary
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE 1
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
|
|
|
|
# device end
|
|
RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
|
|
RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
|
|
|
|
# this must fail on device, but pass on file (which is unfortunate and maybe design mistake)
|
|
RUN "$BD_FAIL" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE))
|
|
RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
|
|
RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
|
|
RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
|
|
}
|
|
|
|
command -v $STRACE >/dev/null || unset STRACE
|
|
test -x $BW_UNIT || skip "Run \"make `basename $BW_UNIT`\" first"
|
|
|
|
FAILS=0
|
|
WARNS=0
|
|
DEVSIZEMB=2
|
|
DEVSIZE=$((DEVSIZEMB*1024*1024))
|
|
|
|
PAGE_SIZE=$(getconf PAGE_SIZE)
|
|
echo "System PAGE_SIZE=$PAGE_SIZE"
|
|
|
|
echo "Run tests in local filesystem"
|
|
falloc $DEVSIZEMB $LOCAL_FILE || fail "Failed to create file in local filesystem."
|
|
BSIZE=$(stat -c "%o" $LOCAL_FILE)
|
|
if [ $BSIZE -gt $((512*1024)) ]; then
|
|
echo "Detected file block size: $BSIZE bytes"
|
|
echo "Tuning it down to system page size ($PAGE_SIZE bytes)"
|
|
BSIZE=$PAGE_SIZE
|
|
fi
|
|
run_all $LOCAL_FILE
|
|
|
|
[ $(id -u) -eq 0 ] || {
|
|
echo "WARNING: You must be root to run remaining tests."
|
|
test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"
|
|
cleanup
|
|
exit 0
|
|
}
|
|
|
|
DEVBSIZE=512
|
|
BSIZE=$DEVBSIZE
|
|
EXP=0
|
|
DEVSIZEMBIMG=32
|
|
|
|
echo "# Create classic 512B drive"
|
|
echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
|
|
add_device dev_size_mb=$DEVSIZEMB sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
|
|
run_all $DEV
|
|
cleanup
|
|
add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
|
|
run_all_in_fs
|
|
cleanup
|
|
|
|
EXP=3
|
|
echo "# Create desktop-class 4K drive"
|
|
echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
|
|
add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
|
|
run_all $DEV
|
|
BSIZE=$((DEVBSIZE*(1<<EXP)))
|
|
run_all $DEV
|
|
cleanup
|
|
|
|
add_device dev_size_mb=$DEVSIZEMBIMG physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
|
|
run_all_in_fs
|
|
cleanup
|
|
|
|
DEVBSIZE=4096
|
|
BSIZE=$DEVBSIZE
|
|
EXP=0
|
|
echo "# Create enterprise-class 4K drive"
|
|
echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
|
|
add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
|
|
run_all $DEV
|
|
cleanup
|
|
add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
|
|
run_all_in_fs
|
|
cleanup
|
|
|
|
test $WARNS -eq 0 || echo "(WARNING: $WARNS suspicious result(s) in total)"
|
|
test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"
|