| #!/bin/bash |
| # Regression tests for tuna |
| # (c) 2008 Red Hat Inc. |
| # Arnaldo Carvalho de Melo <acme@redhat.com> |
| # Released under the GPLv2 |
| |
| dprint() { |
| [ -n "$VERBOSE" ] && echo $1 |
| } |
| |
| ktpidof() { |
| echo $(ps ax -To pid,cmd | grep "\[$1.*\]" | head -1 | cut -d'[' -f 1) |
| } |
| |
| get_rtprio() { |
| echo $(chrt -p $1 | grep priority | cut -d ':' -f 2) |
| } |
| |
| get_policy() { |
| echo $(chrt -p $1 | grep policy | cut -d ':' -f 2) |
| } |
| |
| get_affinity() { |
| echo $(taskset -p $1 | grep 'current affinity' | cut -d ':' -f 2) |
| } |
| |
| get_nr_processors() { |
| echo $(grep -i "^processor.*: " /proc/cpuinfo | tail -1 | cut -d ':' -f 2) |
| } |
| |
| get_nr_cpu_sockets() { |
| echo $(grep "^physical id" /proc/cpuinfo | cut -d: -f2 | sort -u | wc -l) |
| } |
| |
| die() { |
| [ -z "$VERBOSE" ] && echo -n "$2: " |
| echo $1 |
| rtctl --file $INITIAL reset |
| taskset -p $INITIAL_INIT_AFFINITY 1 > /dev/null |
| rm -rf $TESTUNA_DIR |
| exit 1 |
| } |
| |
| die_with_a_diff() { |
| [ -n "$VERBOSE" ] && diff -u $INITIAL $NEW |
| die "$1" |
| } |
| |
| tuna_save() { |
| tuna --save $TEMPCONF |
| grep -v '^# rtctl --file ' $TEMPCONF > $1 |
| rm -f $TEMPCONF |
| } |
| |
| die_if_not_saved() { |
| dprint "$2" |
| tuna_save $NEW |
| (diff -u $INITIAL $NEW | diffstat | \ |
| grep -q "[ \t]*1 file changed, $1 insertions*(+), $1 deletions*(-)") || |
| die_with_a_diff 'FAILED!' "$2" |
| } |
| |
| die_if_conf_changed() { |
| dprint "$1" |
| tuna_save $NEW |
| diff -qu $INITIAL $NEW > /dev/null || die_with_a_diff 'FAILED!' "$1": |
| } |
| |
| die_if_zero() { |
| dprint "$2" |
| [ $1 -eq 0 ] && die 'FAILED!' "$2" |
| } |
| |
| die_if_not_zero() { |
| dprint "$2" |
| [ $1 -ne 0 ] && die 'FAILED!' "$2" |
| } |
| |
| die_if_not_equal() { |
| dprint "$3" |
| [ $1 -ne $2 ] && die 'FAILED!' "$3" |
| } |
| |
| die_if_not_str_equal() { |
| dprint "$3" |
| [ $1 != $2 ] && die 'FAILED!' "$3" |
| } |
| |
| TESTUNA_DIR=$(mktemp -d -t testuna.XXXXXX) || exit 1 |
| INITIAL=$TESTUNA_DIR/initial.tuna |
| INITIAL_INIT_AFFINITY=$(get_affinity 1) |
| TEMPCONF=$TESTUNA_DIR/tempnew.tuna |
| NEW=$TESTUNA_DIR/new.tuna |
| |
| [ $# -eq 1 ] && VERBOSE=1 |
| |
| dprint "Saving initial configuration" |
| |
| tuna_save $INITIAL |
| |
| TUNA_RPM_VERSION=$(rpm -q --qf "%{version}\n" tuna) |
| TUNA_BIN_VERSION=$(tuna --version) |
| die_if_not_str_equal "$TUNA_RPM_VERSION" "$TUNA_BIN_VERSION" \ |
| "Verifying --version ($TUNA_BIN_VERSION) matches package version ($TUNA_RPM_VERSION)" |
| |
| rtctl --file $INITIAL reset |
| |
| die_if_conf_changed "Replaying initial config" |
| |
| PID=$(ktpidof "watchdog") |
| RTPRIO=$(get_rtprio $PID) |
| POLICY=$(get_policy $PID) |
| POLICY=$(echo ${POLICY:6:1} | tr 'A-Z' 'a-z') |
| chrt -$POLICY -p $((RTPRIO - 1)) $PID |
| |
| die_if_not_saved 1 'Saving changes to a kernel thread priority' |
| |
| chrt -$POLICY -p $RTPRIO $PID |
| |
| die_if_conf_changed 'Restoring kernel thread priority' |
| |
| new_policy=$(echo $POLICY | tr fr rf) |
| |
| chrt -$new_policy -p $RTPRIO $PID |
| |
| die_if_not_saved 1 'Changing kernel thread sched policy' |
| |
| chrt -$POLICY -p $RTPRIO $PID |
| |
| die_if_conf_changed 'Restoring kernel thread sched policy' |
| |
| PID=$(ktpidof "kthreadd") |
| AFFINITY=$(get_affinity $PID) |
| |
| taskset -p 0x2 $PID > /dev/null |
| |
| die_if_not_saved 1 'Changing kernel thread SMP affinity mask' |
| |
| taskset -p $AFFINITY $PID > /dev/null |
| |
| die_if_conf_changed 'Restoring kernel thread SMP affinity mask' |
| |
| NR_PROCESSORS=$(get_nr_processors) |
| for PROCESSOR in $(seq 0 $NR_PROCESSORS) ; do |
| taskset -p 0xff 1 > /dev/null |
| |
| PROCESSOR_AFFINITY=$(printf "%#x\n" $((1 << PROCESSOR))) |
| tuna --cpu $PROCESSOR --isolate |
| |
| AFFINITY=0x$(get_affinity 1) |
| |
| die_if_not_zero $((AFFINITY & PROCESSOR_AFFINITY)) "Isolating CPU $PROCESSOR" |
| |
| tuna --cpu $PROCESSOR --include |
| |
| AFFINITY=0x$(get_affinity 1) |
| |
| die_if_zero $((AFFINITY & PROCESSOR_AFFINITY)) "Including CPU $PROCESSOR" |
| done |
| |
| NEW_AFFINITY=$((1 << NR_PROCESSORS | 1)) |
| |
| if [ $NR_PROCESSORS -gt 2 ]; then |
| tuna --cpu=0,$NR_PROCESSORS --isolate |
| |
| for PID in $(cd /proc; ls -d [0-9]*) ; do |
| [ -n "$(cat /proc/$PID/cmdline 2> /dev/null)" ] || continue |
| AFFINITY=0x$(get_affinity $PID) || continue |
| |
| die_if_not_zero $((AFFINITY & NEW_AFFINITY)) \ |
| "Verifying isolation of first and last processor for PID $PID" |
| done |
| fi |
| |
| tuna --cpu=0,$NR_PROCESSORS --include |
| |
| AFFINITY=0x$(get_affinity 1) |
| |
| die_if_not_equal $((AFFINITY & NEW_AFFINITY)) $NEW_AFFINITY "Including first and last processor" |
| |
| taskset -p 0xff 1 > /dev/null |
| |
| NEW_AFFINITY=$((1 << NR_PROCESSORS | 1)) |
| |
| tuna --cpu=0,$NR_PROCESSORS --thread 1 --move |
| |
| AFFINITY=0x$(get_affinity 1) |
| |
| die_if_not_equal $((AFFINITY & NEW_AFFINITY)) $NEW_AFFINITY "Moving init to just first and last processor" |
| |
| NR_CPU_SOCKETS=$(get_nr_cpu_sockets) |
| if [ $NR_CPU_SOCKETS -ge 2 ]; then |
| CPU1_SIBLINGS=$(printf "%d" 0x$(cat /sys/devices/system/cpu/cpu1/topology/core_siblings | cut -d',' -f2)) |
| CPU1_SOCKET=$(cat /sys/devices/system/cpu/cpu1/topology/physical_package_id) |
| |
| tuna --sockets=$CPU1_SOCKET --isolate |
| AFFINITY=0x$(get_affinity 1) |
| die_if_not_zero $((AFFINITY & CPU1_SIBLINGS)) \ |
| "Verifying isolation of socket $CPU1_SOCKET" |
| |
| tuna --sockets=$CPU1_SOCKET --include |
| AFFINITY=0x$(get_affinity 1) |
| die_if_not_equal $((AFFINITY & CPU1_SIBLINGS)) $CPU1_SIBLINGS \ |
| "Verifying inclusion of socket $CPU1_SOCKET" |
| |
| tuna --sockets=$CPU1_SOCKET --isolate |
| tuna --sockets=$CPU1_SOCKET --thread 1 --move |
| AFFINITY=0x$(get_affinity 1) |
| die_if_not_equal $((AFFINITY & CPU1_SIBLINGS)) $CPU1_SIBLINGS "Moving init to CPU socket $CPU1_SOCKET" |
| fi |
| |
| if [ $NR_PROCESSORS -gt 2 ]; then |
| THREAD_PREFIX="watchdog/" |
| PID=$(ps h -C ${THREAD_PREFIX}0 -o pid) |
| RTPRIO=$(get_rtprio $PID) |
| NEW_RTPRIO=$((RTPRIO - 1)) |
| tuna -t $THREAD_PREFIX* -p $NEW_RTPRIO |
| for CPU in $(seq 0 $((NR_PROCESSORS - 1))); do |
| PID=$(ps h -C ${THREAD_PREFIX}$CPU -o pid) |
| RTPRIO=$(get_rtprio $PID) |
| die_if_not_equal $RTPRIO $NEW_RTPRIO "Using --thread globbing" |
| done |
| fi |
| |
| taskset -p $INITIAL_INIT_AFFINITY 1 > /dev/null |
| rtctl --file $INITIAL reset |
| |
| echo 'PASS: Healthy tuna, no lead found, eat!' |
| |
| exit 0 |