1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0+ 3# 4# Run a series of tests under KVM. By default, this series is specified 5# by the relevant CFLIST file, but can be overridden by the --configs 6# command-line argument. 7# 8# Usage: kvm.sh [ options ] 9# 10# Copyright (C) IBM Corporation, 2011 11# 12# Authors: Paul E. McKenney <paulmck@linux.ibm.com> 13 14scriptname=$0 15args="$*" 16 17T="`mktemp -d ${TMPDIR-/tmp}/kvm.sh.XXXXXX`" 18trap 'rm -rf $T' 0 19 20cd `dirname $scriptname`/../../../../../ 21 22# This script knows only English. 23LANG=en_US.UTF-8; export LANG 24 25dur=$((30*60)) 26dryrun="" 27RCUTORTURE="`pwd`/tools/testing/selftests/rcutorture"; export RCUTORTURE 28PATH=${RCUTORTURE}/bin:$PATH; export PATH 29. functions.sh 30 31TORTURE_ALLOTED_CPUS="`identify_qemu_vcpus`" 32TORTURE_DEFCONFIG=defconfig 33TORTURE_BOOT_IMAGE="" 34TORTURE_BUILDONLY= 35TORTURE_INITRD="$RCUTORTURE/initrd"; export TORTURE_INITRD 36TORTURE_KCONFIG_ARG="" 37TORTURE_KCONFIG_GDB_ARG="" 38TORTURE_BOOT_GDB_ARG="" 39TORTURE_QEMU_GDB_ARG="" 40TORTURE_JITTER_START="" 41TORTURE_JITTER_STOP="" 42TORTURE_KCONFIG_KASAN_ARG="" 43TORTURE_KCONFIG_KCSAN_ARG="" 44TORTURE_KMAKE_ARG="" 45TORTURE_NO_AFFINITY="" 46TORTURE_QEMU_MEM=512 47torture_qemu_mem_default=1 48TORTURE_REMOTE= 49TORTURE_SHUTDOWN_GRACE=180 50TORTURE_SUITE=rcu 51TORTURE_MOD=rcutorture 52TORTURE_TRUST_MAKE="" 53debuginfo="CONFIG_DEBUG_INFO_NONE=n CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y" 54resdir="" 55configs="" 56cpus=0 57ds=`date +%Y.%m.%d-%H.%M.%S` 58jitter="-1" 59 60startdate="`date`" 61starttime="`get_starttime`" 62 63usage () { 64 echo "Usage: $scriptname optional arguments:" 65 echo " --allcpus" 66 echo " --bootargs kernel-boot-arguments" 67 echo " --bootimage relative-path-to-kernel-boot-image" 68 echo " --buildonly" 69 echo " --configs \"config-file list w/ repeat factor (3*TINY01)\"" 70 echo " --cpus N" 71 echo " --datestamp string" 72 echo " --defconfig string" 73 echo " --debug-info" 74 echo " --dryrun batches|scenarios|sched|script" 75 echo " --duration minutes | <seconds>s | <hours>h | <days>d" 76 echo " --gdb" 77 echo " --help" 78 echo " --interactive" 79 echo " --jitter N [ maxsleep (us) [ maxspin (us) ] ]" 80 echo " --kasan" 81 echo " --kconfig Kconfig-options" 82 echo " --kcsan" 83 echo " --kill-previous" 84 echo " --kmake-arg kernel-make-arguments" 85 echo " --mac nn:nn:nn:nn:nn:nn" 86 echo " --memory megabytes|nnnG" 87 echo " --no-affinity" 88 echo " --no-initrd" 89 echo " --qemu-args qemu-arguments" 90 echo " --qemu-cmd qemu-system-..." 91 echo " --remote" 92 echo " --results absolute-pathname" 93 echo " --shutdown-grace seconds" 94 echo " --torture lock|rcu|rcuscale|refscale|scf|X*" 95 echo " --trust-make" 96 exit 1 97} 98 99while test $# -gt 0 100do 101 case "$1" in 102 --allcpus) 103 cpus=$TORTURE_ALLOTED_CPUS 104 max_cpus=$TORTURE_ALLOTED_CPUS 105 ;; 106 --bootargs|--bootarg) 107 checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--' 108 TORTURE_BOOTARGS="$TORTURE_BOOTARGS $2" 109 shift 110 ;; 111 --bootimage) 112 checkarg --bootimage "(relative path to kernel boot image)" "$#" "$2" '[a-zA-Z0-9][a-zA-Z0-9_]*' '^--' 113 TORTURE_BOOT_IMAGE="$2" 114 shift 115 ;; 116 --buildonly|--build-only) 117 TORTURE_BUILDONLY=1 118 ;; 119 --configs|--config) 120 checkarg --configs "(list of config files)" "$#" "$2" '^[^/.a-z]\+$' '^--' 121 configs="$configs $2" 122 shift 123 ;; 124 --cpus) 125 checkarg --cpus "(number)" "$#" "$2" '^[0-9]*$' '^--' 126 cpus=$2 127 TORTURE_ALLOTED_CPUS="$2" 128 if test -z "$TORTURE_REMOTE" 129 then 130 max_cpus="`identify_qemu_vcpus`" 131 if test "$TORTURE_ALLOTED_CPUS" -gt "$max_cpus" 132 then 133 TORTURE_ALLOTED_CPUS=$max_cpus 134 fi 135 fi 136 shift 137 ;; 138 --datestamp) 139 checkarg --datestamp "(relative pathname)" "$#" "$2" '^[a-zA-Z0-9._/-]*$' '^--' 140 ds=$2 141 shift 142 ;; 143 --debug-info|--debuginfo) 144 if test -z "$TORTURE_KCONFIG_KCSAN_ARG" && test -z "$TORTURE_BOOT_GDB_ARG" 145 then 146 TORTURE_KCONFIG_KCSAN_ARG="$debuginfo"; export TORTURE_KCONFIG_KCSAN_ARG 147 TORTURE_BOOT_GDB_ARG="nokaslr"; export TORTURE_BOOT_GDB_ARG 148 else 149 echo "Ignored redundant --debug-info (implied by --kcsan &c)" 150 fi 151 ;; 152 --defconfig) 153 checkarg --defconfig "defconfigtype" "$#" "$2" '^[^/][^/]*$' '^--' 154 TORTURE_DEFCONFIG=$2 155 shift 156 ;; 157 --dryrun) 158 checkarg --dryrun "batches|sched|script" $# "$2" 'batches\|scenarios\|sched\|script' '^--' 159 dryrun=$2 160 shift 161 ;; 162 --duration) 163 checkarg --duration "(minutes)" $# "$2" '^[0-9][0-9]*\(s\|m\|h\|d\|\)$' '^error' 164 mult=60 165 if echo "$2" | grep -q 's$' 166 then 167 mult=1 168 elif echo "$2" | grep -q 'h$' 169 then 170 mult=3600 171 elif echo "$2" | grep -q 'd$' 172 then 173 mult=86400 174 fi 175 ts=`echo $2 | sed -e 's/[smhd]$//'` 176 dur=$(($ts*mult)) 177 shift 178 ;; 179 --gdb) 180 TORTURE_KCONFIG_GDB_ARG="$debuginfo"; export TORTURE_KCONFIG_GDB_ARG 181 TORTURE_BOOT_GDB_ARG="nokaslr"; export TORTURE_BOOT_GDB_ARG 182 TORTURE_QEMU_GDB_ARG="-s -S"; export TORTURE_QEMU_GDB_ARG 183 ;; 184 --help|-h) 185 usage 186 ;; 187 --interactive) 188 TORTURE_QEMU_INTERACTIVE=1; export TORTURE_QEMU_INTERACTIVE 189 ;; 190 --jitter) 191 checkarg --jitter "(# threads [ sleep [ spin ] ])" $# "$2" '^-\{,1\}[0-9]\+\( \+[0-9]\+\)\{,2\} *$' '^error$' 192 jitter="$2" 193 shift 194 ;; 195 --kasan) 196 TORTURE_KCONFIG_KASAN_ARG="$debuginfo CONFIG_KASAN=y"; export TORTURE_KCONFIG_KASAN_ARG 197 if test -n "$torture_qemu_mem_default" 198 then 199 TORTURE_QEMU_MEM=2G 200 fi 201 ;; 202 --kconfig|--kconfigs) 203 checkarg --kconfig "(Kconfig options)" $# "$2" '^\(#CHECK#\)\?CONFIG_[A-Z0-9_]\+=\([ynm]\|-\?[0-9]\+\|"[^"]*"\)\( \+\(#CHECK#\)\?CONFIG_[A-Z0-9_]\+=\([ynm]\|-\?[0-9]\+\|"[^"]*"\)\)* *$' '^error$' 204 TORTURE_KCONFIG_ARG="`echo "$TORTURE_KCONFIG_ARG $2" | sed -e 's/^ *//' -e 's/ *$//'`" 205 shift 206 ;; 207 --kcsan) 208 TORTURE_KCONFIG_KCSAN_ARG="$debuginfo CONFIG_KCSAN=y CONFIG_KCSAN_STRICT=y CONFIG_KCSAN_REPORT_ONCE_IN_MS=100000 CONFIG_KCSAN_VERBOSE=y CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y"; export TORTURE_KCONFIG_KCSAN_ARG 209 ;; 210 --kill-previous) 211 TORTURE_KILL_PREVIOUS=1 212 ;; 213 --kmake-arg|--kmake-args) 214 checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$' 215 TORTURE_KMAKE_ARG="`echo "$TORTURE_KMAKE_ARG $2" | sed -e 's/^ *//' -e 's/ *$//'`" 216 shift 217 ;; 218 --mac) 219 checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error 220 TORTURE_QEMU_MAC=$2 221 shift 222 ;; 223 --memory) 224 checkarg --memory "(memory size)" $# "$2" '^[0-9]\+[MG]\?$' error 225 TORTURE_QEMU_MEM=$2 226 torture_qemu_mem_default= 227 shift 228 ;; 229 --no-affinity) 230 TORTURE_NO_AFFINITY="no-affinity" 231 ;; 232 --no-initrd) 233 TORTURE_INITRD=""; export TORTURE_INITRD 234 ;; 235 --qemu-args|--qemu-arg) 236 checkarg --qemu-args "(qemu arguments)" $# "$2" '^-' '^error' 237 TORTURE_QEMU_ARG="`echo "$TORTURE_QEMU_ARG $2" | sed -e 's/^ *//' -e 's/ *$//'`" 238 shift 239 ;; 240 --qemu-cmd) 241 checkarg --qemu-cmd "(qemu-system-...)" $# "$2" 'qemu-system-' '^--' 242 TORTURE_QEMU_CMD="$2" 243 shift 244 ;; 245 --remote) 246 TORTURE_REMOTE=1 247 ;; 248 --results) 249 checkarg --results "(absolute pathname)" "$#" "$2" '^/' '^error' 250 resdir=$2 251 shift 252 ;; 253 --shutdown-grace) 254 checkarg --shutdown-grace "(seconds)" "$#" "$2" '^[0-9]*$' '^error' 255 TORTURE_SHUTDOWN_GRACE=$2 256 shift 257 ;; 258 --torture) 259 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuscale\|refscale\|scf\|X.*\)$' '^--' 260 TORTURE_SUITE=$2 261 TORTURE_MOD="`echo $TORTURE_SUITE | sed -e 's/^\(lock\|rcu\|scf\)$/\1torture/'`" 262 shift 263 if test "$TORTURE_SUITE" = rcuscale || test "$TORTURE_SUITE" = refscale 264 then 265 # If you really want jitter for refscale or 266 # rcuscale, specify it after specifying the rcuscale 267 # or the refscale. (But why jitter in these cases?) 268 jitter=0 269 fi 270 ;; 271 --trust-make) 272 TORTURE_TRUST_MAKE="y" 273 ;; 274 *) 275 echo Unknown argument $1 276 usage 277 ;; 278 esac 279 shift 280done 281 282# Prevent concurrent kvm.sh runs on the same source tree. The flock 283# is automatically released when the script exits, even if killed. 284TORTURE_LOCK="$RCUTORTURE/.kvm.sh.lock" 285 286# Terminate any processes holding the lock file, if requested. 287if test -n "$TORTURE_KILL_PREVIOUS" 288then 289 if test -e "$TORTURE_LOCK" 290 then 291 echo "Killing processes holding $TORTURE_LOCK..." 292 if fuser -k "$TORTURE_LOCK" >/dev/null 2>&1 293 then 294 sleep 2 295 echo "Previous kvm.sh processes killed." 296 else 297 echo "No processes were holding the lock." 298 fi 299 else 300 echo "No lock file exists, nothing to kill." 301 fi 302fi 303 304if test -z "$dryrun" 305then 306 # Create a file descriptor and flock it, so that when kvm.sh (and its 307 # children) exit, the flock is released by the kernel automatically. 308 exec 9>"$TORTURE_LOCK" 309 if ! flock -n 9 310 then 311 echo "ERROR: Another kvm.sh instance is already running on this tree." 312 echo " Lock file: $TORTURE_LOCK" 313 echo " To run kvm.sh, kill all existing kvm.sh runs first (--kill-previous)." 314 exit 1 315 fi 316fi 317 318if test -n "$dryrun" || test -z "$TORTURE_INITRD" || tools/testing/selftests/rcutorture/bin/mkinitrd.sh 319then 320 : 321else 322 echo No initrd and unable to create one, aborting test >&2 323 exit 1 324fi 325 326CONFIGFRAG=${RCUTORTURE}/configs/${TORTURE_SUITE}; export CONFIGFRAG 327 328defaultconfigs="`tr '\012' ' ' < $CONFIGFRAG/CFLIST`" 329if test -z "$configs" 330then 331 configs=$defaultconfigs 332fi 333 334if test -z "$resdir" 335then 336 resdir=$RCUTORTURE/res 337fi 338 339# Create a file of test-name/#cpus pairs, sorted by decreasing #cpus. 340configs_derep= 341for CF in $configs 342do 343 case $CF in 344 [0-9]\**|[0-9][0-9]\**|[0-9][0-9][0-9]\**|[0-9][0-9][0-9][0-9]\**) 345 config_reps=`echo $CF | sed -e 's/\*.*$//'` 346 CF1=`echo $CF | sed -e 's/^[^*]*\*//'` 347 ;; 348 *) 349 config_reps=1 350 CF1=$CF 351 ;; 352 esac 353 for ((cur_rep=0;cur_rep<$config_reps;cur_rep++)) 354 do 355 configs_derep="$configs_derep $CF1" 356 done 357done 358touch $T/cfgcpu 359configs_derep="`echo $configs_derep | sed -e "s/\<CFLIST\>/$defaultconfigs/g"`" 360if test -n "$TORTURE_KCONFIG_GDB_ARG" 361then 362 if test "`echo $configs_derep | wc -w`" -gt 1 363 then 364 echo "The --config list is: $configs_derep." 365 echo "Only one --config permitted with --gdb, terminating." 366 exit 1 367 fi 368fi 369echo 'BEGIN {' > $T/cfgcpu.awk 370for CF1 in `echo $configs_derep | tr -s ' ' '\012' | sort -u` 371do 372 if test -f "$CONFIGFRAG/$CF1" 373 then 374 if echo "$TORTURE_KCONFIG_ARG" | grep -q '\<CONFIG_NR_CPUS=' 375 then 376 echo "$TORTURE_KCONFIG_ARG" | tr -s ' ' | tr ' ' '\012' > $T/KCONFIG_ARG 377 cpu_count=`configNR_CPUS.sh $T/KCONFIG_ARG` 378 else 379 cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF1` 380 fi 381 cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF1" "$cpu_count"` 382 cpu_count=`configfrag_boot_maxcpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF1" "$cpu_count"` 383 echo 'scenariocpu["'"$CF1"'"] = '"$cpu_count"';' >> $T/cfgcpu.awk 384 else 385 echo "The --configs file $CF1 does not exist, terminating." 386 exit 1 387 fi 388done 389cat << '___EOF___' >> $T/cfgcpu.awk 390} 391{ 392 for (i = 1; i <= NF; i++) 393 print $i, scenariocpu[$i]; 394} 395___EOF___ 396echo $configs_derep | awk -f $T/cfgcpu.awk > $T/cfgcpu 397sort -k2nr $T/cfgcpu -T="$T" > $T/cfgcpu.sort 398 399# Use a greedy bin-packing algorithm, sorting the list accordingly. 400awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus ' 401BEGIN { 402 njobs = 0; 403} 404 405{ 406 # Read file of tests and corresponding required numbers of CPUs. 407 cf[njobs] = $1; 408 cpus[njobs] = $2; 409 njobs++; 410} 411 412END { 413 batch = 0; 414 nc = -1; 415 416 # Each pass through the following loop creates on test batch that 417 # can be executed concurrently given ncpus. Note that a given test 418 # that requires more than the available CPUs will run in its own 419 # batch. Such tests just have to make do with what is available. 420 while (nc != ncpus) { 421 batch++; 422 nc = ncpus; 423 424 # Each pass through the following loop considers one 425 # test for inclusion in the current batch. 426 for (i = 0; i < njobs; i++) { 427 if (done[i]) 428 continue; # Already part of a batch. 429 if (nc >= cpus[i] || nc == ncpus) { 430 431 # This test fits into the current batch. 432 done[i] = batch; 433 nc -= cpus[i]; 434 if (nc <= 0) 435 break; # Too-big test in its own batch. 436 } 437 } 438 } 439 440 # Dump out the tests in batch order. 441 for (b = 1; b <= batch; b++) 442 for (i = 0; i < njobs; i++) 443 if (done[i] == b) 444 print cf[i], cpus[i]; 445}' 446 447# Generate a script to execute the tests in appropriate batches. 448cat << ___EOF___ > $T/script 449CONFIGFRAG="$CONFIGFRAG"; export CONFIGFRAG 450RCUTORTURE="$RCUTORTURE"; export RCUTORTURE 451PATH="$PATH"; export PATH 452TORTURE_ALLOTED_CPUS="$TORTURE_ALLOTED_CPUS"; export TORTURE_ALLOTED_CPUS 453TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE 454TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY 455TORTURE_DEFCONFIG="$TORTURE_DEFCONFIG"; export TORTURE_DEFCONFIG 456TORTURE_INITRD="$TORTURE_INITRD"; export TORTURE_INITRD 457TORTURE_KCONFIG_ARG="$TORTURE_KCONFIG_ARG"; export TORTURE_KCONFIG_ARG 458TORTURE_KCONFIG_GDB_ARG="$TORTURE_KCONFIG_GDB_ARG"; export TORTURE_KCONFIG_GDB_ARG 459TORTURE_BOOT_GDB_ARG="$TORTURE_BOOT_GDB_ARG"; export TORTURE_BOOT_GDB_ARG 460TORTURE_QEMU_GDB_ARG="$TORTURE_QEMU_GDB_ARG"; export TORTURE_QEMU_GDB_ARG 461TORTURE_KCONFIG_KASAN_ARG="$TORTURE_KCONFIG_KASAN_ARG"; export TORTURE_KCONFIG_KASAN_ARG 462TORTURE_KCONFIG_KCSAN_ARG="$TORTURE_KCONFIG_KCSAN_ARG"; export TORTURE_KCONFIG_KCSAN_ARG 463TORTURE_KMAKE_ARG="$TORTURE_KMAKE_ARG"; export TORTURE_KMAKE_ARG 464TORTURE_MOD="$TORTURE_MOD"; export TORTURE_MOD 465TORTURE_NO_AFFINITY="$TORTURE_NO_AFFINITY"; export TORTURE_NO_AFFINITY 466TORTURE_QEMU_CMD="$TORTURE_QEMU_CMD"; export TORTURE_QEMU_CMD 467TORTURE_QEMU_INTERACTIVE="$TORTURE_QEMU_INTERACTIVE"; export TORTURE_QEMU_INTERACTIVE 468TORTURE_QEMU_MAC="$TORTURE_QEMU_MAC"; export TORTURE_QEMU_MAC 469TORTURE_QEMU_MEM="$TORTURE_QEMU_MEM"; export TORTURE_QEMU_MEM 470TORTURE_SHUTDOWN_GRACE="$TORTURE_SHUTDOWN_GRACE"; export TORTURE_SHUTDOWN_GRACE 471TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE 472TORTURE_TRUST_MAKE="$TORTURE_TRUST_MAKE"; export TORTURE_TRUST_MAKE 473if ! test -e $resdir 474then 475 mkdir -p "$resdir" || : 476fi 477mkdir -p $resdir/$ds 478TORTURE_RESDIR="$resdir/$ds"; export TORTURE_RESDIR 479TORTURE_STOPFILE="$resdir/$ds/STOP.1"; export TORTURE_STOPFILE 480echo Results directory: $resdir/$ds 481echo $scriptname $args 482touch $resdir/$ds/log 483echo $scriptname $args >> $resdir/$ds/log 484echo ${TORTURE_SUITE} > $resdir/$ds/torture_suite 485mktestid.sh $resdir/$ds 486___EOF___ 487kvm-assign-cpus.sh /sys/devices/system/node > $T/cpuarray.awk 488kvm-get-cpus-script.sh $T/cpuarray.awk $T/dumpbatches.awk 489cat << '___EOF___' >> $T/dumpbatches.awk 490BEGIN { 491 i = 0; 492} 493 494{ 495 cf[i] = $1; 496 cpus[i] = $2; 497 i++; 498} 499 500# Dump out the scripting required to run one test batch. 501function dump(first, pastlast, batchnum, affinitylist) 502{ 503 print "echo ----Start batch " batchnum ": `date` | tee -a " rd "log"; 504 print "needqemurun=" 505 jn=1 506 njitter = 0; 507 split(jitter, ja); 508 if (ja[1] == -1 && ncpus == 0) 509 njitter = 1; 510 else if (ja[1] == -1) 511 njitter = ncpus; 512 else 513 njitter = ja[1]; 514 print "TORTURE_JITTER_START=\". jitterstart.sh " njitter " " rd " " dur " " ja[2] " " ja[3] "\"; export TORTURE_JITTER_START"; 515 print "TORTURE_JITTER_STOP=\". jitterstop.sh " rd " \"; export TORTURE_JITTER_STOP" 516 for (j = first; j < pastlast; j++) { 517 cpusr[jn] = cpus[j]; 518 if (cfrep[cf[j]] == "") { 519 cfr[jn] = cf[j]; 520 cfrep[cf[j]] = 1; 521 } else { 522 cfrep[cf[j]]++; 523 cfr[jn] = cf[j] "." cfrep[cf[j]]; 524 } 525 builddir=rd cfr[jn] "/build"; 526 if (cpusr[jn] > ncpus && ncpus != 0) 527 ovf = "-ovf"; 528 else 529 ovf = ""; 530 print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date` | tee -a " rd "log"; 531 print "mkdir " rd cfr[jn] " || :"; 532 print "touch " builddir ".wait"; 533 affinitylist = ""; 534 if (gotcpus()) { 535 affinitylist = nextcpus(cpusr[jn]); 536 } 537 if (affinitylist ~ /^[0-9,-][0-9,-]*$/) 538 print "export TORTURE_AFFINITY=" affinitylist; 539 else 540 print "export TORTURE_AFFINITY="; 541 print "kvm-test-1-run.sh " CONFIGDIR cf[j], rd cfr[jn], dur " \"" TORTURE_QEMU_ARG "\" \"" TORTURE_BOOTARGS "\" > " rd cfr[jn] "/kvm-test-1-run.sh.out 2>&1 &" 542 print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date` | tee -a " rd "log"; 543 print "while test -f " builddir ".wait" 544 print "do" 545 print "\tsleep 1" 546 print "done" 547 print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date` | tee -a " rd "log"; 548 jn++; 549 } 550 print "runfiles=" 551 for (j = 1; j < jn; j++) { 552 builddir=rd cfr[j] "/build"; 553 if (TORTURE_BUILDONLY) 554 print "rm -f " builddir ".ready" 555 else 556 print "mv " builddir ".ready " builddir ".run" 557 print "runfiles=\"$runfiles " builddir ".run\"" 558 fi 559 print "if test -f \"" rd cfr[j] "/builtkernel\"" 560 print "then" 561 print "\techo ----", cfr[j], cpusr[j] ovf ": Kernel present. `date` | tee -a " rd "log"; 562 print "\tneedqemurun=1" 563 print "fi" 564 } 565 if (TORTURE_BUILDONLY && njitter != 0) { 566 njitter = 0; 567 print "echo Build-only run, so suppressing jitter | tee -a " rd "log" 568 } 569 if (TORTURE_BUILDONLY) { 570 print "needqemurun=" 571 } 572 print "if test -n \"$needqemurun\"" 573 print "then" 574 print "\techo ---- Starting kernels. `date` | tee -a " rd "log"; 575 print "\t$TORTURE_JITTER_START"; 576 print "\twhile ls $runfiles > /dev/null 2>&1" 577 print "\tdo" 578 print "\t\t:" 579 print "\tdone" 580 print "\t$TORTURE_JITTER_STOP"; 581 print "\techo ---- All kernel runs complete. `date` | tee -a " rd "log"; 582 print "else" 583 print "\twait" 584 print "\techo ---- No kernel runs. `date` | tee -a " rd "log"; 585 print "fi" 586 for (j = 1; j < jn; j++) { 587 print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results: | tee -a " rd "log"; 588 print "cat " rd cfr[j] "/kvm-test-1-run.sh.out | tee -a " rd "log"; 589 } 590} 591 592END { 593 njobs = i; 594 nc = ncpus; 595 first = 0; 596 batchnum = 1; 597 598 # Each pass through the following loop considers one test. 599 for (i = 0; i < njobs; i++) { 600 if (ncpus == 0) { 601 # Sequential test specified, each test its own batch. 602 dump(i, i + 1, batchnum); 603 first = i; 604 batchnum++; 605 } else if (nc < cpus[i] && i != 0) { 606 # Out of CPUs, dump out a batch. 607 dump(first, i, batchnum); 608 first = i; 609 nc = ncpus; 610 batchnum++; 611 } 612 # Account for the CPUs needed by the current test. 613 nc -= cpus[i]; 614 } 615 # Dump the last batch. 616 if (ncpus != 0) 617 dump(first, i, batchnum); 618} 619___EOF___ 620awk < $T/cfgcpu.pack \ 621 -v TORTURE_BUILDONLY="$TORTURE_BUILDONLY" \ 622 -v CONFIGDIR="$CONFIGFRAG/" \ 623 -v RCUTORTURE="$RCUTORTURE" \ 624 -v ncpus=$cpus \ 625 -v jitter="$jitter" \ 626 -v rd=$resdir/$ds/ \ 627 -v dur=$dur \ 628 -v TORTURE_QEMU_ARG="$TORTURE_QEMU_ARG" \ 629 -v TORTURE_BOOTARGS="$TORTURE_BOOTARGS" \ 630 -f $T/dumpbatches.awk >> $T/script 631echo kvm-end-run-stats.sh "$resdir/$ds" "$starttime" >> $T/script 632 633# Extract the tests and their batches from the script. 634grep -E 'Start batch|Starting build\.' $T/script | grep -v ">>" | 635 sed -e 's/:.*$//' -e 's/^echo //' -e 's/-ovf//' | 636 awk ' 637 /^----Start/ { 638 batchno = $3; 639 next; 640 } 641 { 642 print batchno, $1, $2 643 }' > $T/batches 644 645# As above, but one line per batch. 646grep -v '^#' $T/batches | awk ' 647BEGIN { 648 oldbatch = 1; 649} 650 651{ 652 if (oldbatch != $1) { 653 print ++n ". " curbatch; 654 curbatch = ""; 655 oldbatch = $1; 656 } 657 curbatch = curbatch " " $2; 658} 659 660END { 661 print ++n ". " curbatch; 662}' > $T/scenarios 663 664if test "$dryrun" = script 665then 666 cat $T/script 667 exit 0 668elif test "$dryrun" = sched 669then 670 # Extract the test run schedule from the script. 671 grep -E 'Start batch|Starting build\.' $T/script | grep -v ">>" | 672 sed -e 's/:.*$//' -e 's/^echo //' 673 nbuilds="`grep 'Starting build\.' $T/script | 674 grep -v ">>" | sed -e 's/:.*$//' -e 's/^echo //' | 675 awk '{ print $1 }' | grep -v '\.' | wc -l`" 676 echo Total number of builds: $nbuilds 677 nbatches="`grep 'Start batch' $T/script | grep -v ">>" | wc -l`" 678 echo Total number of batches: $nbatches 679 exit 0 680elif test "$dryrun" = batches 681then 682 cat $T/batches 683 exit 0 684elif test "$dryrun" = scenarios 685then 686 cat $T/scenarios 687 exit 0 688else 689 # Not a dryrun. Record the batches and the number of CPUs, then run the script. 690 bash $T/script 691 ret=$? 692 cp $T/batches $resdir/$ds/batches 693 cp $T/scenarios $resdir/$ds/scenarios 694 echo '#' cpus=$cpus >> $resdir/$ds/batches 695 exit $ret 696fi 697 698# Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier 699# Function-graph tracing: ftrace=function_graph ftrace_graph_filter=sched_setaffinity,migration_cpu_stop 700# Also --kconfig "CONFIG_FUNCTION_TRACER=y CONFIG_FUNCTION_GRAPH_TRACER=y" 701# Control buffer size: --bootargs trace_buf_size=3k 702# Get trace-buffer dumps on all oopses: --bootargs ftrace_dump_on_oops 703# Ditto, but dump only the oopsing CPU: --bootargs ftrace_dump_on_oops=orig_cpu 704# Heavy-handed way to also dump on warnings: --bootargs panic_on_warn=1 705