| #!/bin/bash -xe |
| # |
| # Kdump test driver: test case will trigger panic, and then crash |
| # dump. The test result is collected via dumped vmcore. For more |
| # information about kdump dirver please refer to doc/README.kdump. |
| # |
| # Copyright (C) 2008, Intel Corp. |
| # Author: Huang Ying <ying.huang@intel.com> |
| # |
| # This file is based on kdump test case in LTP. |
| # |
| # This file is released under the GPLv2. |
| # |
| |
| sd=$(dirname "$0") |
| export ROOT=`(cd $sd/../../..; pwd)` |
| |
| export driver=kdump |
| |
| . $ROOT/lib/functions.sh |
| setup_path |
| . $ROOT/lib/dirs.sh |
| . $ROOT/lib/mce.sh |
| |
| setup_crontab () |
| { |
| echo "Setup crontab." |
| |
| set +e |
| crontab -r |
| set -e |
| |
| # crontab in some distros will not read from STDIN. |
| |
| cat <<EOF > $WDIR/kdump.cron |
| SHELL=/bin/bash |
| PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin |
| MAILTO=root |
| @reboot cd "$(pwd)"; ${0} $conf >> $WDIR/log 2>&1; cat $WDIR/log > /dev/console |
| EOF |
| |
| crontab $WDIR/kdump.cron |
| |
| echo "Enable cron daemon by default." |
| |
| if [ -f /etc/init.d/crond ]; then |
| cron=crond |
| else |
| # SUSE |
| cron=cron |
| fi |
| |
| # Red Hat and SUSE. |
| if [ -x "/sbin/chkconfig" ]; then |
| /sbin/chkconfig "${cron}" on |
| |
| # Debian and Ubuntu. |
| elif [ -x "/sbin/update-rc.d" ]; then |
| /sbin/update-rc.d "${cron}" defaults |
| fi |
| } |
| |
| setup_kdump () |
| { |
| echo "Start kdump daemon." |
| |
| if [ -f /etc/init.d/kdump ]; then |
| daemon=kdump |
| else |
| #SLE11 |
| daemon=boot.kdump |
| fi |
| |
| /etc/init.d/"${daemon}" restart |
| |
| echo "Enable kdump daemon by default." |
| # Red Hat and SUSE. |
| if [ -x "/sbin/chkconfig" ]; then |
| /sbin/chkconfig "${daemon}" on |
| |
| # Debian and Ubuntu. |
| elif [ -x "/sbin/update-rc.d" ]; then |
| /sbin/update-rc.d "${daemon}" defaults |
| fi |
| } |
| |
| get_klog() |
| { |
| klog=$RDIR/$this_case/klog |
| cat <<EOF > $WDIR/get_klog_gdb.cmd |
| dump memory $klog log_buf log_buf+log_end |
| EOF |
| set +e |
| gdb -batch -batch-silent -x $WDIR/get_klog_gdb.cmd $VMLINUX $vmcore \ |
| > /dev/null 2>&1 |
| ret=$? |
| set -e |
| if [ $ret -eq 0 -a -s $klog ]; then |
| export klog |
| else |
| echo " Failed: can not get kernel log" |
| rm -rf $klog |
| fi |
| } |
| |
| dump_gcov() |
| { |
| if [ -z "$GCOV" ]; then |
| return |
| fi |
| if ! chk_gcov; then |
| echo "gcov is not supported by kernel or there is no " \ |
| "gcov utility installed" |
| echo "disabling gcov support" |
| unset GCOV |
| return |
| fi |
| if [ -z "$KSRC_DIR" ]; then |
| echo " Failed: please set KSRC_DIR for GCOV" |
| return |
| else |
| KSRC_DIR=$(set -P && cd "$KSRC_DIR" && pwd) |
| if [ -z "$KSRC_DIR"]; then |
| echo " Failed: Invalid KSRC_DIR, please check your setup" |
| return |
| fi |
| fi |
| export KSRC_DIR |
| local gcov_head_raw=$WDIR/dump_gcov_head_raw |
| cat <<EOF > $WDIR/dump_gcov_gdb.cmd |
| dump value $gcov_head_raw (void *)gcov_info_head |
| EOF |
| set +e |
| gdb -batch -batch-silent -x $WDIR/dump_gcov_gdb.cmd $VMLINUX $vmcore \ |
| > /dev/null 2>&1 |
| ret=$? |
| set -e |
| if [ $ret -ne 0 -o ! -s $gcov_head_raw ]; then |
| echo " Failed: can not get kernel gcov_info_head" |
| return |
| fi |
| wl=$(stat -c '%s' $gcov_head_raw) |
| h=$(echo -n 0x; od -A n -t x$wl $gcov_head_raw | tr -d ' ') |
| if ! gcovdump -g $h $vmcore &> /dev/null; then |
| echo " Failed: can not dump kernel gcov info" |
| return |
| fi |
| cat <<"EOF" > $WDIR/dump_gcov_deskew.sh |
| fn="$1" |
| bfn=$(basename "$fn") |
| dbfn="${bfn##\.tmp_}" |
| if [ -z "$dbfn" ]; then |
| return |
| fi |
| d=$(dirname "$fn") |
| cp $fn "$d/$dbfn" |
| EOF |
| chmod +x $WDIR/dump_gcov_deskew.sh |
| find $KSRC_DIR \( -name '*.tmp_*gcno' -o -name '*.tmp_*gcda' \) \ |
| -exec $WDIR/dump_gcov_deskew.sh \{\} \; |
| |
| export GCOV=dump |
| } |
| |
| get_result () |
| { |
| vmcore=$(ls -t "${COREDIR}"/*/vmcore* 2>/dev/null | head -1) |
| |
| if [ -n "$vmcore" -a -f "$vmcore" ]; then |
| export vmcore |
| get_klog |
| dump_gcov |
| else |
| echo " Failed: can not get vmcore" |
| fi |
| |
| export reboot=1 |
| |
| $CDIR/$case_sh get_result |
| } |
| |
| verify_case () |
| { |
| if [ -z "$vmcore" ]; then |
| echo " Failed: can not got vmcore" |
| fi |
| $CDIR/$case_sh verify |
| } |
| |
| trigger_case () |
| { |
| # Be careful to define COREDIR. |
| rm -rf "${COREDIR}"/* |
| |
| # Save STDIO buffers. |
| sync |
| $CDIR/$case_sh trigger |
| } |
| |
| # Start test. |
| if [ $# -lt 1 ]; then |
| die "Usage: $0 <config>" |
| fi |
| |
| conf=$(basename "$1") |
| |
| . $CONF_DIR/$conf |
| |
| driver_prepare |
| set_tolerant 1 |
| set_panic_on_oops 0 |
| |
| # Check mandatory variables. |
| if [ -z "${COREDIR}" ]; then |
| die "Fail: some mandatory variables are missing from configuration file." |
| fi |
| |
| # Reboot the machine first to take advantage of boot parameter |
| # changes. |
| if [ ! -f $WDIR/stamps/setupped ]; then |
| echo "Setup test environment." |
| |
| setup_crontab |
| |
| $SDIR/setup.sh $CONF_DIR/$conf |
| |
| echo > $WDIR/stamps/setupped |
| |
| echo "System is going to reboot." |
| /sbin/shutdown -r now |
| sleep 60 |
| exit -1 |
| fi |
| |
| #if mce_inject is a module, it is ensured to have been loaded |
| if modinfo mce_inject > /dev/null 2>&1; then |
| if ! lsmod | grep -q mce_inject; then |
| if ! modprobe mce_inject; then |
| die "module mce_inject isn't supported ?" |
| fi |
| fi |
| fi |
| |
| for case_sh in ${CASES}; do |
| for this_case in $($CDIR/$case_sh enumerate); do |
| export this_case |
| _this_case=$(echo $this_case | tr '/' '_') |
| |
| if [ -f $WDIR/stamps/${_this_case}_done ]; then |
| continue |
| fi |
| |
| # First Test. |
| if [ ! -f $WDIR/stamps/first_test_checked ]; then |
| echo "First test..." |
| echo "Verify Boot Loader." |
| if ! grep 'crashkernel=' /proc/cmdline; then |
| die "Fail: error changing Boot Loader, no crashkernel=." |
| fi |
| setup_kdump |
| echo > $WDIR/stamps/first_test_checked |
| fi |
| |
| if [ ! -f $WDIR/stamps/${_this_case}_triggered ]; then |
| echo > $WDIR/stamps/${_this_case}_triggered |
| |
| mkdir -p $RDIR/$this_case |
| rm -rf $RDIR/$this_case/* |
| echo -e "\n$this_case:" | tee -a $RDIR/result |
| |
| echo "Running current test $this_case." |
| |
| trigger_case | tee -a $RDIR/result |
| |
| triggering=1 |
| fi |
| |
| sleep 5 |
| |
| if [ -z "$triggering" ]; then |
| (get_result; verify_case) | tee -a $RDIR/result |
| else |
| echo " Failed: Failed to trigger kdump" | tee -a $RDIR/result |
| fi |
| echo > $WDIR/stamps/${_this_case}_done |
| |
| # Wait for system to fully boot and leave a chance for user to |
| # stop test |
| sleep 55 |
| done |
| done |
| |
| echo "Test run complete" | tee -a $RDIR/result |
| |
| # We are done. |
| # Reset. |
| crontab -r |
| |
| exit 0 |