1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0+ 3# 4# Usage: kvm-series.sh config-list commit-id-list [ kvm.sh parameters ] 5# 6# Tests the specified list of unadorned configs ("TREE01 SRCU-P" but not 7# "CFLIST" or "3*TRACE01") and an indication of a set of commits to test, 8# then runs each commit through the specified list of commits using kvm.sh. 9# The runs are grouped into a -series/config/commit directory tree. 10# Each run defaults to a duration of one minute. 11# 12# Run in top-level Linux source directory. Please note that this is in 13# no way a replacement for "git bisect"!!! 14# 15# This script is intended to replace kvm-check-branches.sh by providing 16# ease of use and faster execution. 17 18T="`mktemp -d ${TMPDIR-/tmp}/kvm-series.sh.XXXXXX`"; export T 19trap 'rm -rf $T' 0 20 21scriptname=$0 22args="$*" 23 24config_list="${1}" 25if test -z "${config_list}" 26then 27 echo "$0: Need a quoted list of --config arguments for first argument." 28 exit 1 29fi 30if test -z "${config_list}" || echo "${config_list}" | grep -q '\*' 31then 32 echo "$0: Repetition ('*') not allowed in config list." 33 exit 1 34fi 35config_list_len="`echo ${config_list} | wc -w | awk '{ print $1; }'`" 36 37commit_list="${2}" 38if test -z "${commit_list}" 39then 40 echo "$0: Need a list of commits (e.g., HEAD^^^..) for second argument." 41 exit 2 42fi 43git log --pretty=format:"%h" "${commit_list}" > $T/commits 44ret=$? 45if test "${ret}" -ne 0 46then 47 echo "$0: Invalid commit list ('${commit_list}')." 48 exit 2 49fi 50sha1_list=`cat $T/commits` 51sha1_list_len="`echo ${sha1_list} | wc -w | awk '{ print $1; }'`" 52 53shift 54shift 55 56RCUTORTURE="`pwd`/tools/testing/selftests/rcutorture"; export RCUTORTURE 57PATH=${RCUTORTURE}/bin:$PATH; export PATH 58RES="${RCUTORTURE}/res"; export RES 59. functions.sh 60 61ret=0 62nbuildfail=0 63nrunfail=0 64nsuccess=0 65ncpus=0 66buildfaillist= 67runfaillist= 68successlist= 69cursha1="`git rev-parse --abbrev-ref HEAD`" 70ds="`date +%Y.%m.%d-%H.%M.%S`-series" 71DS="${RES}/${ds}"; export DS 72startdate="`date`" 73starttime="`get_starttime`" 74 75echo " --- " $scriptname $args | tee -a $T/log 76echo " --- Results directory: " $ds | tee -a $T/log 77 78# Do all builds. Iterate through commits within a given scenario 79# because builds normally go faster from one commit to the next within a 80# given scenario. In contrast, switching scenarios on each rebuild will 81# often force a full rebuild due to Kconfig differences, for example, 82# turning preemption on and off. Defer actual runs in order to run 83# lots of them concurrently on large systems. 84touch $T/torunlist 85n2build="$((config_list_len*sha1_list_len))" 86nbuilt=0 87for config in ${config_list} 88do 89 sha_n=0 90 for sha in ${sha1_list} 91 do 92 sha1=${sha_n}.${sha} # Enable "sort -k1nr" to list commits in order. 93 echo 94 echo Starting ${config}/${sha1} "($((nbuilt+1)) of ${n2build})" at `date` | tee -a $T/log 95 git checkout --detach "${sha}" 96 tools/testing/selftests/rcutorture/bin/kvm.sh --configs "$config" --datestamp "$ds/${config}/${sha1}" --duration 1 --build-only --trust-make "$@" 97 curret=$? 98 if test "${curret}" -ne 0 99 then 100 nbuildfail=$((nbuildfail+1)) 101 buildfaillist="$buildfaillist ${config}/${sha1}(${curret})" 102 else 103 batchncpus="`grep -v "^# cpus=" "${DS}/${config}/${sha1}/batches" | awk '{ sum += $3 } END { print sum }'`" 104 echo run_one_qemu ${sha_n} ${config}/${sha1} ${batchncpus} >> $T/torunlist 105 if test "${ncpus}" -eq 0 106 then 107 ncpus="`grep "^# cpus=" "${DS}/${config}/${sha1}/batches" | sed -e 's/^# cpus=//'`" 108 case "${ncpus}" in 109 ^[0-9]*$) 110 ;; 111 *) 112 ncpus=0 113 ;; 114 esac 115 fi 116 fi 117 if test "${ret}" -eq 0 118 then 119 ret=${curret} 120 fi 121 sha_n=$((sha_n+1)) 122 nbuilt=$((nbuilt+1)) 123 done 124done 125 126# If the user did not specify the number of CPUs, use them all. 127if test "${ncpus}" -eq 0 128then 129 ncpus="`identify_qemu_vcpus`" 130fi 131 132cpusused=0 133touch $T/successlistfile 134touch $T/faillistfile 135n2run="`wc -l $T/torunlist | awk '{ print $1; }'`" 136nrun=0 137 138# do_run_one_qemu ds resultsdir qemu_curout 139# 140# Start the specified qemu run and record its success or failure. 141do_run_one_qemu () { 142 local ret 143 local ds="$1" 144 local resultsdir="$2" 145 local qemu_curout="$3" 146 147 tools/testing/selftests/rcutorture/bin/kvm-again.sh "${DS}/${resultsdir}" --link inplace-force > ${qemu_curout} 2>&1 148 ret=$? 149 if test "${ret}" -eq 0 150 then 151 echo ${resultsdir} >> $T/successlistfile 152 # Successful run, so remove large files. 153 rm -f ${DS}/${resultsdir}/{vmlinux,bzImage,System.map,Module.symvers} 154 else 155 echo "${resultsdir}(${ret})" >> $T/faillistfile 156 fi 157} 158 159# cleanup_qemu_batch batchncpus 160# 161# Update success and failure lists, files, and counts at the end of 162# a batch. 163cleanup_qemu_batch () { 164 local batchncpus="$1" 165 166 echo Waiting, cpusused=${cpusused}, ncpus=${ncpus} `date` | tee -a $T/log 167 wait 168 cpusused="${batchncpus}" 169 nsuccessbatch="`wc -l $T/successlistfile | awk '{ print $1 }'`" 170 nsuccess=$((nsuccess+nsuccessbatch)) 171 successlist="$successlist `cat $T/successlistfile`" 172 rm $T/successlistfile 173 touch $T/successlistfile 174 nfailbatch="`wc -l $T/faillistfile | awk '{ print $1 }'`" 175 nrunfail=$((nrunfail+nfailbatch)) 176 runfaillist="$runfaillist `cat $T/faillistfile`" 177 rm $T/faillistfile 178 touch $T/faillistfile 179} 180 181# run_one_qemu sha_n config/sha1 batchncpus 182# 183# Launch into the background the sha_n-th qemu job whose results directory 184# is config/sha1 and which uses batchncpus CPUs. Once we reach a job that 185# would overflow the number of available CPUs, wait for the previous jobs 186# to complete and record their results. 187run_one_qemu () { 188 local sha_n="$1" 189 local config_sha1="$2" 190 local batchncpus="$3" 191 local qemu_curout 192 193 cpusused=$((cpusused+batchncpus)) 194 if test "${cpusused}" -gt $ncpus 195 then 196 cleanup_qemu_batch "${batchncpus}" 197 fi 198 echo Starting ${config_sha1} using ${batchncpus} CPUs "($((nrun+1)) of ${n2run})" `date` 199 qemu_curout="${DS}/${config_sha1}/qemu-series" 200 do_run_one_qemu "$ds" "${config_sha1}" ${qemu_curout} & 201 nrun="$((nrun+1))" 202} 203 204# Re-ordering the runs will mess up the affinity chosen at build time 205# (among other things, over-using CPU 0), so suppress it. 206TORTURE_NO_AFFINITY="no-affinity"; export TORTURE_NO_AFFINITY 207 208# Run the kernels (if any) that built correctly. 209echo | tee -a $T/log # Put a blank line between build and run messages. 210. $T/torunlist 211cleanup_qemu_batch "${batchncpus}" 212 213# Get back to initial checkout/SHA-1. 214git checkout "${cursha1}" 215 216# Throw away leading and trailing space characters for fmt. 217successlist="`echo ${successlist} | sed -e 's/^ *//' -e 's/ *$//'`" 218buildfaillist="`echo ${buildfaillist} | sed -e 's/^ *//' -e 's/ *$//'`" 219runfaillist="`echo ${runfaillist} | sed -e 's/^ *//' -e 's/ *$//'`" 220 221# Print lists of successes, build failures, and run failures, if any. 222if test "${nsuccess}" -gt 0 223then 224 echo | tee -a $T/log 225 echo ${nsuccess} SUCCESSES: | tee -a $T/log 226 echo ${successlist} | fmt | tee -a $T/log 227fi 228if test "${nbuildfail}" -gt 0 229then 230 echo | tee -a $T/log 231 echo ${nbuildfail} BUILD FAILURES: | tee -a $T/log 232 echo ${buildfaillist} | fmt | tee -a $T/log 233fi 234if test "${nrunfail}" -gt 0 235then 236 echo | tee -a $T/log 237 echo ${nrunfail} RUN FAILURES: | tee -a $T/log 238 echo ${runfaillist} | fmt | tee -a $T/log 239fi 240 241# If there were build or runtime failures, map them to commits. 242if test "${nbuildfail}" -gt 0 || test "${nrunfail}" -gt 0 243then 244 echo | tee -a $T/log 245 echo Build failures across commits: | tee -a $T/log 246 echo ${buildfaillist} | tr ' ' '\012' | sed -e 's,^[^/]*/,,' -e 's/([0-9]*)//' | 247 sort | uniq -c | sort -k2n | tee -a $T/log 248fi 249 250# Print run summary. 251echo | tee -a $T/log 252echo Started at $startdate, ended at `date`, duration `get_starttime_duration $starttime`. | tee -a $T/log 253echo Summary: Successes: ${nsuccess} " "Build Failures: ${nbuildfail} " "Runtime Failures: ${nrunfail}| tee -a $T/log 254cp $T/log ${DS} 255 256exit "${ret}" 257