1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0+ 3# 4# Rerun a series of tests under KVM. 5# 6# Usage: kvm-again.sh /path/to/old/run [ options ] 7# 8# Copyright (C) 2021 Facebook, Inc. 9# 10# Authors: Paul E. McKenney <paulmck@kernel.org> 11 12scriptname=$0 13args="$*" 14 15T="`mktemp -d ${TMPDIR-/tmp}/kvm-again.sh.XXXXXX`" 16trap 'rm -rf $T' 0 17 18if ! test -d tools/testing/selftests/rcutorture/bin 19then 20 echo $scriptname must be run from top-level directory of kernel source tree. 21 exit 1 22fi 23 24oldrun=$1 25shift 26if ! test -d "$oldrun" 27then 28 echo "Usage: $scriptname /path/to/old/run [ options ]" 29 exit 1 30fi 31if ! cp "$oldrun/scenarios" $T/scenarios.oldrun 32then 33 # Later on, can reconstitute this from console.log files. 34 echo Prior run scenarios file does not exist: $oldrun/scenarios 35 exit 1 36fi 37 38if test -f "$oldrun/torture_suite" 39then 40 torture_suite="`cat $oldrun/torture_suite`" 41elif test -f "$oldrun/TORTURE_SUITE" 42then 43 torture_suite="`cat $oldrun/TORTURE_SUITE`" 44else 45 echo "Prior run torture_suite file does not exist: $oldrun/{torture_suite,TORTURE_SUITE}" 46 exit 1 47fi 48 49RCUTORTURE="`pwd`/tools/testing/selftests/rcutorture"; export RCUTORTURE 50PATH=${RCUTORTURE}/bin:$PATH; export PATH 51. functions.sh 52 53bootargs= 54dryrun= 55dur= 56default_link="cp -R" 57resdir="`pwd`/tools/testing/selftests/rcutorture/res" 58rundir="$resdir/`date +%Y.%m.%d-%H.%M.%S-again`" 59got_datestamp= 60got_rundir= 61 62startdate="`date`" 63starttime="`get_starttime`" 64 65usage () { 66 echo "Usage: $scriptname $oldrun [ arguments ]:" 67 echo " --bootargs kernel-boot-arguments" 68 echo " --datestamp string" 69 echo " --dryrun" 70 echo " --duration minutes | <seconds>s | <hours>h | <days>d" 71 echo " --link hard|soft|copy|inplace|inplace-force" 72 echo " --remote" 73 echo " --rundir /new/res/path" 74 echo "Command line: $scriptname $args" 75 exit 1 76} 77 78while test $# -gt 0 79do 80 case "$1" in 81 --bootargs|--bootarg) 82 checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--' 83 bootargs="$bootargs $2" 84 shift 85 ;; 86 --datestamp) 87 checkarg --datestamp "(relative pathname)" "$#" "$2" '^[a-zA-Z0-9._/-]*$' '^--' 88 if test -n "$got_rundir" || test -n "$got_datestamp" 89 then 90 echo Only one of --datestamp or --rundir may be specified 91 usage 92 fi 93 got_datestamp=y 94 ds=$2 95 rundir="$resdir/$ds" 96 if test -e "$rundir" 97 then 98 echo "--datestamp $2: Already exists." 99 usage 100 fi 101 shift 102 ;; 103 --dryrun) 104 dryrun=1 105 ;; 106 --duration) 107 checkarg --duration "(minutes)" $# "$2" '^[0-9][0-9]*\(s\|m\|h\|d\|\)$' '^error' 108 mult=60 109 if echo "$2" | grep -q 's$' 110 then 111 mult=1 112 elif echo "$2" | grep -q 'h$' 113 then 114 mult=3600 115 elif echo "$2" | grep -q 'd$' 116 then 117 mult=86400 118 fi 119 ts=`echo $2 | sed -e 's/[smhd]$//'` 120 dur=$(($ts*mult)) 121 shift 122 ;; 123 --link) 124 checkarg --link "hard|soft|copy|inplace|inplace-force" "$#" "$2" 'hard\|soft\|copy\|inplace\|inplace-force' '^--' 125 case "$2" in 126 copy) 127 arg_link="cp -R" 128 ;; 129 hard) 130 arg_link="cp -Rl" 131 ;; 132 soft) 133 arg_link="cp -Rs" 134 ;; 135 inplace) 136 arg_link="inplace" 137 rundir="$oldrun" 138 ;; 139 inplace-force) 140 arg_link="inplace-force" 141 rundir="$oldrun" 142 ;; 143 esac 144 shift 145 ;; 146 --remote) 147 arg_remote=1 148 default_link="cp -as" 149 ;; 150 --rundir) 151 checkarg --rundir "(absolute pathname)" "$#" "$2" '^/' '^error' 152 if test -n "$got_rundir" || test -n "$got_datestamp" 153 then 154 echo Only one of --datestamp or --rundir may be specified 155 usage 156 fi 157 got_rundir=y 158 rundir=$2 159 if test -e "$rundir" 160 then 161 echo "--rundir $2: Already exists." 162 usage 163 fi 164 shift 165 ;; 166 *) 167 if test -n "$1" 168 then 169 echo Unknown argument $1 170 usage 171 fi 172 ;; 173 esac 174 shift 175done 176if test -z "$arg_link" 177then 178 arg_link="$default_link" 179fi 180 181echo ---- Re-run results directory: $rundir 182 183if test "$oldrun" != "$rundir" 184then 185 # Copy old run directory tree over and adjust. 186 mkdir -p "`dirname "$rundir"`" 187 if ! $arg_link "$oldrun" "$rundir" 188 then 189 echo "Cannot copy from $oldrun to $rundir." 190 usage 191 fi 192 rm -f "$rundir"/*/{console.log,console.log.diags,qemu_pid,qemu-pid,qemu-retval,Warnings,kvm-test-1-run.sh.out,kvm-test-1-run-qemu.sh.out,vmlinux} "$rundir"/log 193 touch "$rundir/log" 194 echo $scriptname $args | tee -a "$rundir/log" 195 echo $oldrun > "$rundir/re-run" 196 if ! test -d "$rundir/../../bin" 197 then 198 $arg_link "$oldrun/../../bin" "$rundir/../.." 199 fi 200else 201 # Check for a run having already happened. 202 find "$rundir" -name console.log -print > $T/oldrun-console.log 203 if test -s $T/oldrun-console.log 204 then 205 echo Run already took place in $rundir 206 if test "$arg_link" = inplace 207 then 208 usage 209 fi 210 fi 211fi 212 213# Find runs to be done based on their qemu-cmd files. 214for i in $rundir/*/qemu-cmd 215do 216 cp "$i" $T 217 qemu_cmd_dir="`dirname "$i"`" 218 kernel_dir="`echo $qemu_cmd_dir | sed -e 's/\.[0-9]\+$//'`" 219 jitter_dir="`dirname "$kernel_dir"`" 220 kvm-transform.sh "$kernel_dir/bzImage" "$qemu_cmd_dir/console.log" "$jitter_dir" "$dur" "$bootargs" < $T/qemu-cmd > $i 221 if test -n "$arg_remote" 222 then 223 echo "# TORTURE_KCONFIG_GDB_ARG=''" >> $i 224 fi 225done 226 227# Extract settings from the last qemu-cmd file transformed above. 228grep '^#' $i | sed -e 's/^# //' > $T/qemu-cmd-settings 229. $T/qemu-cmd-settings 230 231grep -v '^#' $T/scenarios.oldrun | awk ' 232{ 233 curbatch = ""; 234 for (i = 2; i <= NF; i++) 235 curbatch = curbatch " " $i; 236 print "kvm-test-1-run-batch.sh" curbatch; 237}' > $T/runbatches.sh 238 239if test -n "$dryrun" 240then 241 echo ---- Dryrun complete, directory: $rundir | tee -a "$rundir/log" 242else 243 ( cd "$rundir"; sh $T/runbatches.sh ) | tee -a "$rundir/log" 244 kvm-end-run-stats.sh "$rundir" "$starttime" 245fi 246