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