1*eda14cbcSMatt Macy#!/usr/bin/env bash 2*eda14cbcSMatt Macy 3*eda14cbcSMatt Macy# 4*eda14cbcSMatt Macy# CDDL HEADER START 5*eda14cbcSMatt Macy# 6*eda14cbcSMatt Macy# This file and its contents are supplied under the terms of the 7*eda14cbcSMatt Macy# Common Development and Distribution License ("CDDL"), version 1.0. 8*eda14cbcSMatt Macy# You may only use this file in accordance with the terms of version 9*eda14cbcSMatt Macy# 1.0 of the CDDL. 10*eda14cbcSMatt Macy# 11*eda14cbcSMatt Macy# A full copy of the text of the CDDL should have accompanied this 12*eda14cbcSMatt Macy# source. A copy of the CDDL is also available via the Internet at 13*eda14cbcSMatt Macy# http://www.illumos.org/license/CDDL. 14*eda14cbcSMatt Macy# 15*eda14cbcSMatt Macy# CDDL HEADER END 16*eda14cbcSMatt Macy# 17*eda14cbcSMatt Macy 18*eda14cbcSMatt Macy# 19*eda14cbcSMatt Macy# Copyright (c) 2015 by Delphix. All rights reserved. 20*eda14cbcSMatt Macy# Copyright (C) 2016 Lawrence Livermore National Security, LLC. 21*eda14cbcSMatt Macy# 22*eda14cbcSMatt Macy 23*eda14cbcSMatt MacyBASE_DIR=$(dirname "$0") 24*eda14cbcSMatt MacySCRIPT_COMMON=common.sh 25*eda14cbcSMatt Macyif [ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]; then 26*eda14cbcSMatt Macy . "${BASE_DIR}/${SCRIPT_COMMON}" 27*eda14cbcSMatt Macyelse 28*eda14cbcSMatt Macy echo "Missing helper script ${SCRIPT_COMMON}" && exit 1 29*eda14cbcSMatt Macyfi 30*eda14cbcSMatt Macy 31*eda14cbcSMatt Macy# shellcheck disable=SC2034 32*eda14cbcSMatt MacyPROG=zloop.sh 33*eda14cbcSMatt MacyGDB=${GDB:-gdb} 34*eda14cbcSMatt Macy 35*eda14cbcSMatt MacyDEFAULTWORKDIR=/var/tmp 36*eda14cbcSMatt MacyDEFAULTCOREDIR=/var/tmp/zloop 37*eda14cbcSMatt Macy 38*eda14cbcSMatt Macyfunction usage 39*eda14cbcSMatt Macy{ 40*eda14cbcSMatt Macy echo -e "\n$0 [-t <timeout>] [ -s <vdev size> ] [-c <dump directory>]" \ 41*eda14cbcSMatt Macy "[ -- [extra ztest parameters]]\n" \ 42*eda14cbcSMatt Macy "\n" \ 43*eda14cbcSMatt Macy " This script runs ztest repeatedly with randomized arguments.\n" \ 44*eda14cbcSMatt Macy " If a crash is encountered, the ztest logs, any associated\n" \ 45*eda14cbcSMatt Macy " vdev files, and core file (if one exists) are moved to the\n" \ 46*eda14cbcSMatt Macy " output directory ($DEFAULTCOREDIR by default). Any options\n" \ 47*eda14cbcSMatt Macy " after the -- end-of-options marker will be passed to ztest.\n" \ 48*eda14cbcSMatt Macy "\n" \ 49*eda14cbcSMatt Macy " Options:\n" \ 50*eda14cbcSMatt Macy " -t Total time to loop for, in seconds. If not provided,\n" \ 51*eda14cbcSMatt Macy " zloop runs forever.\n" \ 52*eda14cbcSMatt Macy " -s Size of vdev devices.\n" \ 53*eda14cbcSMatt Macy " -f Specify working directory for ztest vdev files.\n" \ 54*eda14cbcSMatt Macy " -c Specify a core dump directory to use.\n" \ 55*eda14cbcSMatt Macy " -m Max number of core dumps to allow before exiting.\n" \ 56*eda14cbcSMatt Macy " -l Create 'ztest.core.N' symlink to core directory.\n" \ 57*eda14cbcSMatt Macy " -h Print this help message.\n" \ 58*eda14cbcSMatt Macy "" >&2 59*eda14cbcSMatt Macy} 60*eda14cbcSMatt Macy 61*eda14cbcSMatt Macyfunction or_die 62*eda14cbcSMatt Macy{ 63*eda14cbcSMatt Macy # shellcheck disable=SC2068 64*eda14cbcSMatt Macy $@ 65*eda14cbcSMatt Macy # shellcheck disable=SC2181 66*eda14cbcSMatt Macy if [[ $? -ne 0 ]]; then 67*eda14cbcSMatt Macy # shellcheck disable=SC2145 68*eda14cbcSMatt Macy echo "Command failed: $@" 69*eda14cbcSMatt Macy exit 1 70*eda14cbcSMatt Macy fi 71*eda14cbcSMatt Macy} 72*eda14cbcSMatt Macy 73*eda14cbcSMatt Macycase $(uname) in 74*eda14cbcSMatt MacyFreeBSD) 75*eda14cbcSMatt Macy coreglob="z*.core" 76*eda14cbcSMatt Macy ;; 77*eda14cbcSMatt MacyLinux) 78*eda14cbcSMatt Macy # core file helpers 79*eda14cbcSMatt Macy origcorepattern="$(cat /proc/sys/kernel/core_pattern)" 80*eda14cbcSMatt Macy coreglob="$(grep -E -o '^([^|%[:space:]]*)' /proc/sys/kernel/core_pattern)*" 81*eda14cbcSMatt Macy 82*eda14cbcSMatt Macy if [[ $coreglob = "*" ]]; then 83*eda14cbcSMatt Macy echo "Setting core file pattern..." 84*eda14cbcSMatt Macy echo "core" > /proc/sys/kernel/core_pattern 85*eda14cbcSMatt Macy coreglob="$(grep -E -o '^([^|%[:space:]]*)' \ 86*eda14cbcSMatt Macy /proc/sys/kernel/core_pattern)*" 87*eda14cbcSMatt Macy fi 88*eda14cbcSMatt Macy ;; 89*eda14cbcSMatt Macy*) 90*eda14cbcSMatt Macy exit 1 91*eda14cbcSMatt Macy ;; 92*eda14cbcSMatt Macyesac 93*eda14cbcSMatt Macy 94*eda14cbcSMatt Macyfunction core_file 95*eda14cbcSMatt Macy{ 96*eda14cbcSMatt Macy # shellcheck disable=SC2012 disable=2086 97*eda14cbcSMatt Macy printf "%s" "$(ls -tr1 $coreglob 2> /dev/null | head -1)" 98*eda14cbcSMatt Macy} 99*eda14cbcSMatt Macy 100*eda14cbcSMatt Macyfunction core_prog 101*eda14cbcSMatt Macy{ 102*eda14cbcSMatt Macy prog=$ZTEST 103*eda14cbcSMatt Macy core_id=$($GDB --batch -c "$1" | grep "Core was generated by" | \ 104*eda14cbcSMatt Macy tr \' ' ') 105*eda14cbcSMatt Macy # shellcheck disable=SC2076 106*eda14cbcSMatt Macy if [[ "$core_id" =~ "zdb " ]]; then 107*eda14cbcSMatt Macy prog=$ZDB 108*eda14cbcSMatt Macy fi 109*eda14cbcSMatt Macy printf "%s" "$prog" 110*eda14cbcSMatt Macy} 111*eda14cbcSMatt Macy 112*eda14cbcSMatt Macyfunction store_core 113*eda14cbcSMatt Macy{ 114*eda14cbcSMatt Macy core="$(core_file)" 115*eda14cbcSMatt Macy if [[ $ztrc -ne 0 ]] || [[ -f "$core" ]]; then 116*eda14cbcSMatt Macy df -h "$workdir" >>ztest.out 117*eda14cbcSMatt Macy coreid=$(date "+zloop-%y%m%d-%H%M%S") 118*eda14cbcSMatt Macy foundcrashes=$((foundcrashes + 1)) 119*eda14cbcSMatt Macy 120*eda14cbcSMatt Macy # zdb debugging 121*eda14cbcSMatt Macy zdbcmd="$ZDB -U "$workdir/zpool.cache" -dddMmDDG ztest" 122*eda14cbcSMatt Macy zdbdebug=$($zdbcmd 2>&1) 123*eda14cbcSMatt Macy echo -e "$zdbcmd\n" >>ztest.zdb 124*eda14cbcSMatt Macy echo "$zdbdebug" >>ztest.zdb 125*eda14cbcSMatt Macy 126*eda14cbcSMatt Macy dest=$coredir/$coreid 127*eda14cbcSMatt Macy or_die mkdir -p "$dest" 128*eda14cbcSMatt Macy or_die mkdir -p "$dest/vdev" 129*eda14cbcSMatt Macy 130*eda14cbcSMatt Macy if [[ $symlink -ne 0 ]]; then 131*eda14cbcSMatt Macy or_die ln -sf "$dest" ztest.core.$foundcrashes 132*eda14cbcSMatt Macy fi 133*eda14cbcSMatt Macy 134*eda14cbcSMatt Macy echo "*** ztest crash found - moving logs to $dest" 135*eda14cbcSMatt Macy 136*eda14cbcSMatt Macy or_die mv ztest.history "$dest/" 137*eda14cbcSMatt Macy or_die mv ztest.zdb "$dest/" 138*eda14cbcSMatt Macy or_die mv ztest.out "$dest/" 139*eda14cbcSMatt Macy or_die mv "$workdir/ztest*" "$dest/vdev/" 140*eda14cbcSMatt Macy 141*eda14cbcSMatt Macy if [[ -e "$workdir/zpool.cache" ]]; then 142*eda14cbcSMatt Macy or_die mv "$workdir/zpool.cache" "$dest/vdev/" 143*eda14cbcSMatt Macy fi 144*eda14cbcSMatt Macy 145*eda14cbcSMatt Macy # check for core 146*eda14cbcSMatt Macy if [[ -f "$core" ]]; then 147*eda14cbcSMatt Macy coreprog=$(core_prog "$core") 148*eda14cbcSMatt Macy coredebug=$($GDB --batch --quiet \ 149*eda14cbcSMatt Macy -ex "set print thread-events off" \ 150*eda14cbcSMatt Macy -ex "printf \"*\n* Backtrace \n*\n\"" \ 151*eda14cbcSMatt Macy -ex "bt" \ 152*eda14cbcSMatt Macy -ex "printf \"*\n* Libraries \n*\n\"" \ 153*eda14cbcSMatt Macy -ex "info sharedlib" \ 154*eda14cbcSMatt Macy -ex "printf \"*\n* Threads (full) \n*\n\"" \ 155*eda14cbcSMatt Macy -ex "info threads" \ 156*eda14cbcSMatt Macy -ex "printf \"*\n* Backtraces \n*\n\"" \ 157*eda14cbcSMatt Macy -ex "thread apply all bt" \ 158*eda14cbcSMatt Macy -ex "printf \"*\n* Backtraces (full) \n*\n\"" \ 159*eda14cbcSMatt Macy -ex "thread apply all bt full" \ 160*eda14cbcSMatt Macy -ex "quit" "$coreprog" "$core" 2>&1 | \ 161*eda14cbcSMatt Macy grep -v "New LWP") 162*eda14cbcSMatt Macy 163*eda14cbcSMatt Macy # Dump core + logs to stored directory 164*eda14cbcSMatt Macy echo "$coredebug" >>"$dest/ztest.gdb" 165*eda14cbcSMatt Macy or_die mv "$core" "$dest/" 166*eda14cbcSMatt Macy 167*eda14cbcSMatt Macy # Record info in cores logfile 168*eda14cbcSMatt Macy echo "*** core @ $coredir/$coreid/$core:" | \ 169*eda14cbcSMatt Macy tee -a ztest.cores 170*eda14cbcSMatt Macy fi 171*eda14cbcSMatt Macy 172*eda14cbcSMatt Macy if [[ $coremax -gt 0 ]] && 173*eda14cbcSMatt Macy [[ $foundcrashes -ge $coremax ]]; then 174*eda14cbcSMatt Macy echo "exiting... max $coremax allowed cores" 175*eda14cbcSMatt Macy exit 1 176*eda14cbcSMatt Macy else 177*eda14cbcSMatt Macy echo "continuing..." 178*eda14cbcSMatt Macy fi 179*eda14cbcSMatt Macy fi 180*eda14cbcSMatt Macy} 181*eda14cbcSMatt Macy 182*eda14cbcSMatt Macy# parse arguments 183*eda14cbcSMatt Macy# expected format: zloop [-t timeout] [-c coredir] [-- extra ztest args] 184*eda14cbcSMatt Macycoredir=$DEFAULTCOREDIR 185*eda14cbcSMatt Macybasedir=$DEFAULTWORKDIR 186*eda14cbcSMatt Macyrundir="zloop-run" 187*eda14cbcSMatt Macytimeout=0 188*eda14cbcSMatt Macysize="512m" 189*eda14cbcSMatt Macycoremax=0 190*eda14cbcSMatt Macysymlink=0 191*eda14cbcSMatt Macywhile getopts ":ht:m:s:c:f:l" opt; do 192*eda14cbcSMatt Macy case $opt in 193*eda14cbcSMatt Macy t ) [[ $OPTARG -gt 0 ]] && timeout=$OPTARG ;; 194*eda14cbcSMatt Macy m ) [[ $OPTARG -gt 0 ]] && coremax=$OPTARG ;; 195*eda14cbcSMatt Macy s ) [[ $OPTARG ]] && size=$OPTARG ;; 196*eda14cbcSMatt Macy c ) [[ $OPTARG ]] && coredir=$OPTARG ;; 197*eda14cbcSMatt Macy f ) [[ $OPTARG ]] && basedir=$(readlink -f "$OPTARG") ;; 198*eda14cbcSMatt Macy l ) symlink=1 ;; 199*eda14cbcSMatt Macy h ) usage 200*eda14cbcSMatt Macy exit 2 201*eda14cbcSMatt Macy ;; 202*eda14cbcSMatt Macy * ) echo "Invalid argument: -$OPTARG"; 203*eda14cbcSMatt Macy usage 204*eda14cbcSMatt Macy exit 1 205*eda14cbcSMatt Macy esac 206*eda14cbcSMatt Macydone 207*eda14cbcSMatt Macy# pass remaining arguments on to ztest 208*eda14cbcSMatt Macyshift $((OPTIND - 1)) 209*eda14cbcSMatt Macy 210*eda14cbcSMatt Macy# enable core dumps 211*eda14cbcSMatt Macyulimit -c unlimited 212*eda14cbcSMatt Macyexport ASAN_OPTIONS=abort_on_error=1:disable_coredump=0 213*eda14cbcSMatt Macy 214*eda14cbcSMatt Macyif [[ -f "$(core_file)" ]]; then 215*eda14cbcSMatt Macy echo -n "There's a core dump here you might want to look at first... " 216*eda14cbcSMatt Macy core_file 217*eda14cbcSMatt Macy echo 218*eda14cbcSMatt Macy exit 1 219*eda14cbcSMatt Macyfi 220*eda14cbcSMatt Macy 221*eda14cbcSMatt Macyif [[ ! -d $coredir ]]; then 222*eda14cbcSMatt Macy echo "core dump directory ($coredir) does not exist, creating it." 223*eda14cbcSMatt Macy or_die mkdir -p "$coredir" 224*eda14cbcSMatt Macyfi 225*eda14cbcSMatt Macy 226*eda14cbcSMatt Macyif [[ ! -w $coredir ]]; then 227*eda14cbcSMatt Macy echo "core dump directory ($coredir) is not writable." 228*eda14cbcSMatt Macy exit 1 229*eda14cbcSMatt Macyfi 230*eda14cbcSMatt Macy 231*eda14cbcSMatt Macyor_die rm -f ztest.history 232*eda14cbcSMatt Macyor_die rm -f ztest.zdb 233*eda14cbcSMatt Macyor_die rm -f ztest.cores 234*eda14cbcSMatt Macy 235*eda14cbcSMatt Macyztrc=0 # ztest return value 236*eda14cbcSMatt Macyfoundcrashes=0 # number of crashes found so far 237*eda14cbcSMatt Macystarttime=$(date +%s) 238*eda14cbcSMatt Macycurtime=$starttime 239*eda14cbcSMatt Macy 240*eda14cbcSMatt Macy# if no timeout was specified, loop forever. 241*eda14cbcSMatt Macywhile [[ $timeout -eq 0 ]] || [[ $curtime -le $((starttime + timeout)) ]]; do 242*eda14cbcSMatt Macy zopt="-G -VVVVV" 243*eda14cbcSMatt Macy 244*eda14cbcSMatt Macy # start each run with an empty directory 245*eda14cbcSMatt Macy workdir="$basedir/$rundir" 246*eda14cbcSMatt Macy or_die rm -rf "$workdir" 247*eda14cbcSMatt Macy or_die mkdir "$workdir" 248*eda14cbcSMatt Macy 249*eda14cbcSMatt Macy # switch between common arrangements & fully randomized 250*eda14cbcSMatt Macy if [[ $((RANDOM % 2)) -eq 0 ]]; then 251*eda14cbcSMatt Macy mirrors=2 252*eda14cbcSMatt Macy raidz=0 253*eda14cbcSMatt Macy parity=1 254*eda14cbcSMatt Macy vdevs=2 255*eda14cbcSMatt Macy else 256*eda14cbcSMatt Macy mirrors=$(((RANDOM % 3) * 1)) 257*eda14cbcSMatt Macy parity=$(((RANDOM % 3) + 1)) 258*eda14cbcSMatt Macy raidz=$((((RANDOM % 9) + parity + 1) * (RANDOM % 2))) 259*eda14cbcSMatt Macy vdevs=$(((RANDOM % 3) + 3)) 260*eda14cbcSMatt Macy fi 261*eda14cbcSMatt Macy align=$(((RANDOM % 2) * 3 + 9)) 262*eda14cbcSMatt Macy runtime=$((RANDOM % 100)) 263*eda14cbcSMatt Macy passtime=$((RANDOM % (runtime / 3 + 1) + 10)) 264*eda14cbcSMatt Macy 265*eda14cbcSMatt Macy zopt="$zopt -m $mirrors" 266*eda14cbcSMatt Macy zopt="$zopt -r $raidz" 267*eda14cbcSMatt Macy zopt="$zopt -R $parity" 268*eda14cbcSMatt Macy zopt="$zopt -v $vdevs" 269*eda14cbcSMatt Macy zopt="$zopt -a $align" 270*eda14cbcSMatt Macy zopt="$zopt -T $runtime" 271*eda14cbcSMatt Macy zopt="$zopt -P $passtime" 272*eda14cbcSMatt Macy zopt="$zopt -s $size" 273*eda14cbcSMatt Macy zopt="$zopt -f $workdir" 274*eda14cbcSMatt Macy 275*eda14cbcSMatt Macy # shellcheck disable=SC2124 276*eda14cbcSMatt Macy cmd="$ZTEST $zopt $@" 277*eda14cbcSMatt Macy desc="$(date '+%m/%d %T') $cmd" 278*eda14cbcSMatt Macy echo "$desc" | tee -a ztest.history 279*eda14cbcSMatt Macy echo "$desc" >>ztest.out 280*eda14cbcSMatt Macy $cmd >>ztest.out 2>&1 281*eda14cbcSMatt Macy ztrc=$? 282*eda14cbcSMatt Macy grep -E '===|WARNING' ztest.out >>ztest.history 283*eda14cbcSMatt Macy 284*eda14cbcSMatt Macy store_core 285*eda14cbcSMatt Macy 286*eda14cbcSMatt Macy curtime=$(date +%s) 287*eda14cbcSMatt Macydone 288*eda14cbcSMatt Macy 289*eda14cbcSMatt Macyecho "zloop finished, $foundcrashes crashes found" 290*eda14cbcSMatt Macy 291*eda14cbcSMatt Macy# restore core pattern. 292*eda14cbcSMatt Macycase $(uname) in 293*eda14cbcSMatt MacyLinux) 294*eda14cbcSMatt Macy echo "$origcorepattern" > /proc/sys/kernel/core_pattern 295*eda14cbcSMatt Macy ;; 296*eda14cbcSMatt Macy*) 297*eda14cbcSMatt Macy ;; 298*eda14cbcSMatt Macyesac 299*eda14cbcSMatt Macy 300*eda14cbcSMatt Macyuptime >>ztest.out 301*eda14cbcSMatt Macy 302*eda14cbcSMatt Macyif [[ $foundcrashes -gt 0 ]]; then 303*eda14cbcSMatt Macy exit 1 304*eda14cbcSMatt Macyfi 305