| #!/bin/bash |
| |
| TESTS="$@" |
| RET=0 |
| TIMEOUT=60 |
| DMESG_FILTER="cat" |
| TEST_DIR=$(dirname $0) |
| FAILED="" |
| SKIPPED="" |
| MAYBE_FAILED="" |
| TEST_FILES="" |
| declare -A TEST_MAP |
| |
| # Only use /dev/kmsg if running as root |
| DO_KMSG="1" |
| [ "$(id -u)" != "0" ] && DO_KMSG="0" |
| |
| # Include config.local if exists and check TEST_FILES for valid devices |
| if [ -f "$TEST_DIR/config.local" ]; then |
| . $TEST_DIR/config.local |
| for dev in $TEST_FILES; do |
| if [ ! -e "$dev" ]; then |
| echo "Test file $dev not valid" |
| exit 1 |
| fi |
| done |
| for dev in ${TEST_MAP[@]}; do |
| if [ ! -e "$dev" ]; then |
| echo "Test file in map $dev not valid" |
| exit 1 |
| fi |
| done |
| fi |
| |
| _check_dmesg() |
| { |
| local dmesg_marker="$1" |
| local seqres="$2.seqres" |
| |
| if [ $DO_KMSG -eq 0 ]; then |
| return 0 |
| fi |
| |
| dmesg | bash -c "$DMESG_FILTER" | grep -A 9999 "$dmesg_marker" >"${seqres}.dmesg" |
| grep -q -e "kernel BUG at" \ |
| -e "WARNING:" \ |
| -e "BUG:" \ |
| -e "Oops:" \ |
| -e "possible recursive locking detected" \ |
| -e "Internal error" \ |
| -e "INFO: suspicious RCU usage" \ |
| -e "INFO: possible circular locking dependency detected" \ |
| -e "general protection fault:" \ |
| -e "blktests failure" \ |
| "${seqres}.dmesg" |
| # shellcheck disable=SC2181 |
| if [[ $? -eq 0 ]]; then |
| return 1 |
| else |
| rm -f "${seqres}.dmesg" |
| return 0 |
| fi |
| } |
| |
| run_test() |
| { |
| local test_name="$1" |
| local dev="$2" |
| local test_string=$test_name |
| |
| # Specify test string to print |
| if [ -n "$dev" ]; then |
| test_string="$test_name $dev" |
| fi |
| |
| # Log start of the test |
| if [ "$DO_KMSG" -eq 1 ]; then |
| local dmesg_marker="Running test $test_string:" |
| echo $dmesg_marker | tee /dev/kmsg |
| else |
| local dmesg_marker="" |
| echo Running test $test_name $dev |
| fi |
| |
| # Do we have to exclude the test ? |
| echo $TEST_EXCLUDE | grep -w "$test_name" > /dev/null 2>&1 |
| if [ $? -eq 0 ]; then |
| echo "Test skipped" |
| SKIPPED="$SKIPPED <$test_string>" |
| return |
| fi |
| |
| # Run the test |
| timeout -s INT -k $TIMEOUT $TIMEOUT ./$test_name $dev |
| local status=$? |
| |
| # Check test status |
| if [ "$status" -eq 124 ]; then |
| echo "Test $test_name timed out (may not be a failure)" |
| elif [ "$status" -ne 0 ]; then |
| echo "Test $test_name failed with ret $status" |
| FAILED="$FAILED <$test_string>" |
| RET=1 |
| elif ! _check_dmesg "$dmesg_marker" "$test_name"; then |
| echo "Test $test_name failed dmesg check" |
| FAILED="$FAILED <$test_string>" |
| RET=1 |
| elif [ -n "$dev" ]; then |
| sleep .1 |
| ps aux | grep "\[io_wq_manager\]" > /dev/null |
| if [ $? -eq 0 ]; then |
| MAYBE_FAILED="$MAYBE_FAILED $test_string" |
| fi |
| fi |
| } |
| |
| # Run all specified tests |
| for tst in $TESTS; do |
| if [ ! -n "${TEST_MAP[$tst]}" ]; then |
| run_test $tst |
| if [ ! -z "$TEST_FILES" ]; then |
| for dev in $TEST_FILES; do |
| run_test $tst $dev |
| done |
| fi |
| else |
| run_test $tst ${TEST_MAP[$tst]} |
| fi |
| done |
| |
| if [ -n "$SKIPPED" ]; then |
| echo "Tests skipped: $SKIPPED" |
| fi |
| |
| if [ "${RET}" -ne 0 ]; then |
| echo "Tests failed: $FAILED" |
| exit $RET |
| else |
| sleep 1 |
| ps aux | grep "\[io_wq_manager\]" > /dev/null |
| if [ $? -ne 0 ]; then |
| MAYBE_FAILED="" |
| fi |
| if [ ! -z "$MAYBE_FAILED" ]; then |
| echo "Tests _maybe_ failed: $MAYBE_FAILED" |
| fi |
| echo "All tests passed" |
| exit 0 |
| fi |