Merge branches 'doc.2021.01.06a', 'fixes.2021.01.04b', 'kfree_rcu.2021.01.04a', 'mmdumpobj.2021.01.22a', 'nocb.2021.01.06a', 'rt.2021.01.04a', 'stall.2021.01.06a', 'torture.2021.01.12a' and 'tortureall.2021.01.06a' into HEAD
doc.2021.01.06a: Documentation updates. fixes.2021.01.04b: Miscellaneous fixes. kfree_rcu.2021.01.04a: kfree_rcu() updates. mmdumpobj.2021.01.22a: Dump allocation point for memory blocks. nocb.2021.01.06a: RCU callback offload updates and cblist segment lengths. rt.2021.01.04a: Real-time updates. stall.2021.01.06a: RCU CPU stall warning updates. torture.2021.01.12a: Torture-test updates and polling SRCU grace-period API. tortureall.2021.01.06a: Torture-test script updates.
This commit is contained in:
+67
@@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Create a spreadsheet from torture-test Kconfig options and kernel boot
|
||||
# parameters. Run this in the directory containing the scenario files.
|
||||
#
|
||||
# Usage: config2csv path.csv [ "scenario1 scenario2 ..." ]
|
||||
#
|
||||
# By default, this script will take the list of scenarios from the CFLIST
|
||||
# file in that directory, otherwise it will consider only the scenarios
|
||||
# specified on the command line. It will examine each scenario's file
|
||||
# and also its .boot file, if present, and create a column in the .csv
|
||||
# output file. Note that "CFLIST" is a synonym for all the scenarios in the
|
||||
# CFLIST file, which allows easy comparison of those scenarios with selected
|
||||
# scenarios such as BUSTED that are normally omitted from CFLIST files.
|
||||
|
||||
csvout=${1}
|
||||
if test -z "$csvout"
|
||||
then
|
||||
echo "Need .csv output file as first argument."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
defaultconfigs="`tr '\012' ' ' < CFLIST`"
|
||||
if test "$#" -eq 0
|
||||
then
|
||||
scenariosarg=$defaultconfigs
|
||||
else
|
||||
scenariosarg=$*
|
||||
fi
|
||||
scenarios="`echo $scenariosarg | sed -e "s/\<CFLIST\>/$defaultconfigs/g"`"
|
||||
|
||||
T=/tmp/config2latex.sh.$$
|
||||
trap 'rm -rf $T' 0
|
||||
mkdir $T
|
||||
|
||||
cat << '---EOF---' >> $T/p.awk
|
||||
END {
|
||||
---EOF---
|
||||
for i in $scenarios
|
||||
do
|
||||
echo ' s["'$i'"] = 1;' >> $T/p.awk
|
||||
grep -v '^#' < $i | grep -v '^ *$' > $T/p
|
||||
if test -r $i.boot
|
||||
then
|
||||
tr -s ' ' '\012' < $i.boot | grep -v '^#' >> $T/p
|
||||
fi
|
||||
sed -e 's/^[^=]*$/&=?/' < $T/p |
|
||||
sed -e 's/^\([^=]*\)=\(.*\)$/\tp["\1:'"$i"'"] = "\2";\n\tc["\1"] = 1;/' >> $T/p.awk
|
||||
done
|
||||
cat << '---EOF---' >> $T/p.awk
|
||||
ns = asorti(s, ss);
|
||||
nc = asorti(c, cs);
|
||||
for (j = 1; j <= ns; j++)
|
||||
printf ",\"%s\"", ss[j];
|
||||
printf "\n";
|
||||
for (i = 1; i <= nc; i++) {
|
||||
printf "\"%s\"", cs[i];
|
||||
for (j = 1; j <= ns; j++) {
|
||||
printf ",\"%s\"", p[cs[i] ":" ss[j]];
|
||||
}
|
||||
printf "\n";
|
||||
}
|
||||
}
|
||||
---EOF---
|
||||
awk -f $T/p.awk < /dev/null > $T/p.csv
|
||||
cp $T/p.csv $csvout
|
||||
@@ -14,4 +14,5 @@ egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls o
|
||||
grep -v 'ODEBUG: ' |
|
||||
grep -v 'This means that this is a DEBUG kernel and it is' |
|
||||
grep -v 'Warning: unable to open an initial console' |
|
||||
grep -v 'Warning: Failed to add ttynull console. No stdin, stdout, and stderr.*the init process!' |
|
||||
grep -v 'NOHZ tick-stop error: Non-RCU local softirq work is pending, handler'
|
||||
|
||||
@@ -108,6 +108,39 @@ configfrag_hotplug_cpu () {
|
||||
grep -q '^CONFIG_HOTPLUG_CPU=y$' "$1"
|
||||
}
|
||||
|
||||
# get_starttime
|
||||
#
|
||||
# Returns a cookie identifying the current time.
|
||||
get_starttime () {
|
||||
awk 'BEGIN { print systime() }' < /dev/null
|
||||
}
|
||||
|
||||
# get_starttime_duration starttime
|
||||
#
|
||||
# Given the return value from get_starttime, compute a human-readable
|
||||
# string denoting the time since get_starttime.
|
||||
get_starttime_duration () {
|
||||
awk -v starttime=$1 '
|
||||
BEGIN {
|
||||
ts = systime() - starttime;
|
||||
tm = int(ts / 60);
|
||||
th = int(ts / 3600);
|
||||
td = int(ts / 86400);
|
||||
d = td;
|
||||
h = th - td * 24;
|
||||
m = tm - th * 60;
|
||||
s = ts - tm * 60;
|
||||
if (d >= 1)
|
||||
printf "%dd %d:%02d:%02d\n", d, h, m, s
|
||||
else if (h >= 1)
|
||||
printf "%d:%02d:%02d\n", h, m, s
|
||||
else if (m >= 1)
|
||||
printf "%d:%02d.0\n", m, s
|
||||
else
|
||||
print s " seconds"
|
||||
}' < /dev/null
|
||||
}
|
||||
|
||||
# identify_boot_image qemu-cmd
|
||||
#
|
||||
# Returns the relative path to the kernel build image. This will be
|
||||
@@ -170,6 +203,7 @@ identify_qemu () {
|
||||
# and the TORTURE_QEMU_INTERACTIVE environment variable.
|
||||
identify_qemu_append () {
|
||||
echo debug_boot_weak_hash
|
||||
echo panic=-1
|
||||
local console=ttyS0
|
||||
case "$1" in
|
||||
qemu-system-x86_64|qemu-system-i386)
|
||||
@@ -232,7 +266,7 @@ identify_qemu_args () {
|
||||
# Returns the number of virtual CPUs available to the aggregate of the
|
||||
# guest OSes.
|
||||
identify_qemu_vcpus () {
|
||||
lscpu | grep '^CPU(s):' | sed -e 's/CPU(s)://' -e 's/[ ]*//g'
|
||||
getconf _NPROCESSORS_ONLN
|
||||
}
|
||||
|
||||
# print_bug
|
||||
|
||||
@@ -39,12 +39,14 @@ done
|
||||
if test -n "$files"
|
||||
then
|
||||
$editor $files
|
||||
editorret=1
|
||||
else
|
||||
echo No build errors.
|
||||
fi
|
||||
if grep -q -e "--buildonly" < ${rundir}/log
|
||||
then
|
||||
echo Build-only run, no console logs to check.
|
||||
exit $editorret
|
||||
fi
|
||||
|
||||
# Find console logs with errors
|
||||
@@ -62,5 +64,10 @@ then
|
||||
exit 1
|
||||
else
|
||||
echo No errors in console logs.
|
||||
exit 0
|
||||
if test -n "$editorret"
|
||||
then
|
||||
exit $editorret
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -87,15 +87,16 @@ do
|
||||
fi
|
||||
done
|
||||
EDITOR=echo kvm-find-errors.sh "${@: -1}" > $T 2>&1
|
||||
ret=$?
|
||||
builderrors="`tr ' ' '\012' < $T | grep -c '/Make.out.diags'`"
|
||||
if test "$builderrors" -gt 0
|
||||
then
|
||||
echo $builderrors runs with build errors.
|
||||
ret=1
|
||||
fi
|
||||
runerrors="`tr ' ' '\012' < $T | grep -c '/console.log.diags'`"
|
||||
if test "$runerrors" -gt 0
|
||||
then
|
||||
echo $runerrors runs with runtime errors.
|
||||
ret=2
|
||||
fi
|
||||
exit $ret
|
||||
|
||||
@@ -125,7 +125,6 @@ seconds=$4
|
||||
qemu_args=$5
|
||||
boot_args=$6
|
||||
|
||||
kstarttime=`gawk 'BEGIN { print systime() }' < /dev/null`
|
||||
if test -z "$TORTURE_BUILDONLY"
|
||||
then
|
||||
echo ' ---' `date`: Starting kernel
|
||||
@@ -158,6 +157,8 @@ then
|
||||
boot_args="$boot_args $TORTURE_BOOT_GDB_ARG"
|
||||
fi
|
||||
echo $QEMU $qemu_args -m $TORTURE_QEMU_MEM -kernel $KERNEL -append \"$qemu_append $boot_args\" $TORTURE_QEMU_GDB_ARG > $resdir/qemu-cmd
|
||||
echo "# TORTURE_SHUTDOWN_GRACE=$TORTURE_SHUTDOWN_GRACE" >> $resdir/qemu-cmd
|
||||
echo "# seconds=$seconds" >> $resdir/qemu-cmd
|
||||
|
||||
if test -n "$TORTURE_BUILDONLY"
|
||||
then
|
||||
@@ -174,6 +175,7 @@ echo 'echo $! > $resdir/qemu_pid' >> $T/qemu-cmd
|
||||
echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log
|
||||
|
||||
# Attempt to run qemu
|
||||
kstarttime=`gawk 'BEGIN { print systime() }' < /dev/null`
|
||||
( . $T/qemu-cmd; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) &
|
||||
commandcompleted=0
|
||||
if test -z "$TORTURE_KCONFIG_GDB_ARG"
|
||||
@@ -209,7 +211,7 @@ do
|
||||
if test -n "$TORTURE_KCONFIG_GDB_ARG"
|
||||
then
|
||||
:
|
||||
elif test $kruntime -ge $seconds || test -f "$TORTURE_STOPFILE"
|
||||
elif test $kruntime -ge $seconds || test -f "$resdir/../STOP.1"
|
||||
then
|
||||
break;
|
||||
fi
|
||||
@@ -252,16 +254,16 @@ then
|
||||
fi
|
||||
if test $commandcompleted -eq 0 -a -n "$qemu_pid"
|
||||
then
|
||||
if ! test -f "$TORTURE_STOPFILE"
|
||||
if ! test -f "$resdir/../STOP.1"
|
||||
then
|
||||
echo Grace period for qemu job at pid $qemu_pid
|
||||
fi
|
||||
oldline="`tail $resdir/console.log`"
|
||||
while :
|
||||
do
|
||||
if test -f "$TORTURE_STOPFILE"
|
||||
if test -f "$resdir/../STOP.1"
|
||||
then
|
||||
echo "PID $qemu_pid killed due to run STOP request" >> $resdir/Warnings 2>&1
|
||||
echo "PID $qemu_pid killed due to run STOP.1 request" >> $resdir/Warnings 2>&1
|
||||
kill -KILL $qemu_pid
|
||||
break
|
||||
fi
|
||||
|
||||
@@ -47,6 +47,9 @@ cpus=0
|
||||
ds=`date +%Y.%m.%d-%H.%M.%S`
|
||||
jitter="-1"
|
||||
|
||||
startdate="`date`"
|
||||
starttime="`get_starttime`"
|
||||
|
||||
usage () {
|
||||
echo "Usage: $scriptname optional arguments:"
|
||||
echo " --allcpus"
|
||||
@@ -57,7 +60,7 @@ usage () {
|
||||
echo " --cpus N"
|
||||
echo " --datestamp string"
|
||||
echo " --defconfig string"
|
||||
echo " --dryrun sched|script"
|
||||
echo " --dryrun batches|sched|script"
|
||||
echo " --duration minutes | <seconds>s | <hours>h | <days>d"
|
||||
echo " --gdb"
|
||||
echo " --help"
|
||||
@@ -85,7 +88,7 @@ do
|
||||
;;
|
||||
--bootargs|--bootarg)
|
||||
checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--'
|
||||
TORTURE_BOOTARGS="$2"
|
||||
TORTURE_BOOTARGS="$TORTURE_BOOTARGS $2"
|
||||
shift
|
||||
;;
|
||||
--bootimage)
|
||||
@@ -97,8 +100,8 @@ do
|
||||
TORTURE_BUILDONLY=1
|
||||
;;
|
||||
--configs|--config)
|
||||
checkarg --configs "(list of config files)" "$#" "$2" '^[^/]*$' '^--'
|
||||
configs="$2"
|
||||
checkarg --configs "(list of config files)" "$#" "$2" '^[^/]\+$' '^--'
|
||||
configs="$configs $2"
|
||||
shift
|
||||
;;
|
||||
--cpus)
|
||||
@@ -113,7 +116,7 @@ do
|
||||
shift
|
||||
;;
|
||||
--datestamp)
|
||||
checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
|
||||
checkarg --datestamp "(relative pathname)" "$#" "$2" '^[a-zA-Z0-9._-/]*$' '^--'
|
||||
ds=$2
|
||||
shift
|
||||
;;
|
||||
@@ -123,7 +126,7 @@ do
|
||||
shift
|
||||
;;
|
||||
--dryrun)
|
||||
checkarg --dryrun "sched|script" $# "$2" 'sched\|script' '^--'
|
||||
checkarg --dryrun "batches|sched|script" $# "$2" 'batches\|sched\|script' '^--'
|
||||
dryrun=$2
|
||||
shift
|
||||
;;
|
||||
@@ -162,18 +165,18 @@ do
|
||||
;;
|
||||
--kconfig|--kconfigs)
|
||||
checkarg --kconfig "(Kconfig options)" $# "$2" '^CONFIG_[A-Z0-9_]\+=\([ynm]\|[0-9]\+\)\( CONFIG_[A-Z0-9_]\+=\([ynm]\|[0-9]\+\)\)*$' '^error$'
|
||||
TORTURE_KCONFIG_ARG="$2"
|
||||
TORTURE_KCONFIG_ARG="`echo "$TORTURE_KCONFIG_ARG $2" | sed -e 's/^ *//' -e 's/ *$//'`"
|
||||
shift
|
||||
;;
|
||||
--kasan)
|
||||
TORTURE_KCONFIG_KASAN_ARG="CONFIG_DEBUG_INFO=y CONFIG_KASAN=y"; export TORTURE_KCONFIG_KASAN_ARG
|
||||
;;
|
||||
--kcsan)
|
||||
TORTURE_KCONFIG_KCSAN_ARG="CONFIG_DEBUG_INFO=y CONFIG_KCSAN=y CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC=n CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=n CONFIG_KCSAN_REPORT_ONCE_IN_MS=100000 CONFIG_KCSAN_VERBOSE=y CONFIG_KCSAN_INTERRUPT_WATCHER=y"; export TORTURE_KCONFIG_KCSAN_ARG
|
||||
TORTURE_KCONFIG_KCSAN_ARG="CONFIG_DEBUG_INFO=y CONFIG_KCSAN=y CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC=n CONFIG_KCSAN_REPORT_VALUE_CHANGE_ONLY=n CONFIG_KCSAN_REPORT_ONCE_IN_MS=100000 CONFIG_KCSAN_INTERRUPT_WATCHER=y CONFIG_KCSAN_VERBOSE=y CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y"; export TORTURE_KCONFIG_KCSAN_ARG
|
||||
;;
|
||||
--kmake-arg|--kmake-args)
|
||||
checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
|
||||
TORTURE_KMAKE_ARG="$2"
|
||||
TORTURE_KMAKE_ARG="`echo "$TORTURE_KMAKE_ARG $2" | sed -e 's/^ *//' -e 's/ *$//'`"
|
||||
shift
|
||||
;;
|
||||
--mac)
|
||||
@@ -191,7 +194,7 @@ do
|
||||
;;
|
||||
--qemu-args|--qemu-arg)
|
||||
checkarg --qemu-args "(qemu arguments)" $# "$2" '^-' '^error'
|
||||
TORTURE_QEMU_ARG="$2"
|
||||
TORTURE_QEMU_ARG="`echo "$TORTURE_QEMU_ARG $2" | sed -e 's/^ *//' -e 's/ *$//'`"
|
||||
shift
|
||||
;;
|
||||
--qemu-cmd)
|
||||
@@ -232,7 +235,7 @@ do
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$TORTURE_INITRD" || tools/testing/selftests/rcutorture/bin/mkinitrd.sh
|
||||
if test -n "$dryrun" || test -z "$TORTURE_INITRD" || tools/testing/selftests/rcutorture/bin/mkinitrd.sh
|
||||
then
|
||||
:
|
||||
else
|
||||
@@ -283,19 +286,34 @@ then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
for CF1 in $configs_derep
|
||||
echo 'BEGIN {' > $T/cfgcpu.awk
|
||||
for CF1 in `echo $configs_derep | tr -s ' ' '\012' | sort -u`
|
||||
do
|
||||
if test -f "$CONFIGFRAG/$CF1"
|
||||
then
|
||||
cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF1`
|
||||
if echo "$TORTURE_KCONFIG_ARG" | grep -q '\<CONFIG_NR_CPUS='
|
||||
then
|
||||
echo "$TORTURE_KCONFIG_ARG" | tr -s ' ' | tr ' ' '\012' > $T/KCONFIG_ARG
|
||||
cpu_count=`configNR_CPUS.sh $T/KCONFIG_ARG`
|
||||
else
|
||||
cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF1`
|
||||
fi
|
||||
cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF1" "$cpu_count"`
|
||||
cpu_count=`configfrag_boot_maxcpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF1" "$cpu_count"`
|
||||
echo $CF1 $cpu_count >> $T/cfgcpu
|
||||
echo 'scenariocpu["'"$CF1"'"] = '"$cpu_count"';' >> $T/cfgcpu.awk
|
||||
else
|
||||
echo "The --configs file $CF1 does not exist, terminating."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
cat << '___EOF___' >> $T/cfgcpu.awk
|
||||
}
|
||||
{
|
||||
for (i = 1; i <= NF; i++)
|
||||
print $i, scenariocpu[$i];
|
||||
}
|
||||
___EOF___
|
||||
echo $configs_derep | awk -f $T/cfgcpu.awk > $T/cfgcpu
|
||||
sort -k2nr $T/cfgcpu -T="$T" > $T/cfgcpu.sort
|
||||
|
||||
# Use a greedy bin-packing algorithm, sorting the list accordingly.
|
||||
@@ -315,11 +333,10 @@ END {
|
||||
batch = 0;
|
||||
nc = -1;
|
||||
|
||||
# Each pass through the following loop creates on test batch
|
||||
# that can be executed concurrently given ncpus. Note that a
|
||||
# given test that requires more than the available CPUs will run in
|
||||
# their own batch. Such tests just have to make do with what
|
||||
# is available.
|
||||
# Each pass through the following loop creates on test batch that
|
||||
# can be executed concurrently given ncpus. Note that a given test
|
||||
# that requires more than the available CPUs will run in its own
|
||||
# batch. Such tests just have to make do with what is available.
|
||||
while (nc != ncpus) {
|
||||
batch++;
|
||||
nc = ncpus;
|
||||
@@ -375,9 +392,9 @@ if ! test -e $resdir
|
||||
then
|
||||
mkdir -p "$resdir" || :
|
||||
fi
|
||||
mkdir $resdir/$ds
|
||||
mkdir -p $resdir/$ds
|
||||
TORTURE_RESDIR="$resdir/$ds"; export TORTURE_RESDIR
|
||||
TORTURE_STOPFILE="$resdir/$ds/STOP"; export TORTURE_STOPFILE
|
||||
TORTURE_STOPFILE="$resdir/$ds/STOP.1"; export TORTURE_STOPFILE
|
||||
echo Results directory: $resdir/$ds
|
||||
echo $scriptname $args
|
||||
touch $resdir/$ds/log
|
||||
@@ -517,14 +534,19 @@ END {
|
||||
dump(first, i, batchnum);
|
||||
}' >> $T/script
|
||||
|
||||
cat << ___EOF___ >> $T/script
|
||||
echo
|
||||
echo
|
||||
echo " --- `date` Test summary:"
|
||||
echo Results directory: $resdir/$ds
|
||||
kcsan-collapse.sh $resdir/$ds
|
||||
kvm-recheck.sh $resdir/$ds
|
||||
cat << '___EOF___' >> $T/script
|
||||
echo | tee -a $TORTURE_RESDIR/log
|
||||
echo | tee -a $TORTURE_RESDIR/log
|
||||
echo " --- `date` Test summary:" | tee -a $TORTURE_RESDIR/log
|
||||
___EOF___
|
||||
cat << ___EOF___ >> $T/script
|
||||
echo Results directory: $resdir/$ds | tee -a $resdir/$ds/log
|
||||
kcsan-collapse.sh $resdir/$ds | tee -a $resdir/$ds/log
|
||||
kvm-recheck.sh $resdir/$ds > $T/kvm-recheck.sh.out 2>&1
|
||||
___EOF___
|
||||
echo 'ret=$?' >> $T/script
|
||||
echo "cat $T/kvm-recheck.sh.out | tee -a $resdir/$ds/log" >> $T/script
|
||||
echo 'exit $ret' >> $T/script
|
||||
|
||||
if test "$dryrun" = script
|
||||
then
|
||||
@@ -533,13 +555,34 @@ then
|
||||
elif test "$dryrun" = sched
|
||||
then
|
||||
# Extract the test run schedule from the script.
|
||||
egrep 'Start batch|Starting build\.' $T/script |
|
||||
grep -v ">>" |
|
||||
egrep 'Start batch|Starting build\.' $T/script | grep -v ">>" |
|
||||
sed -e 's/:.*$//' -e 's/^echo //'
|
||||
nbuilds="`grep 'Starting build\.' $T/script |
|
||||
grep -v ">>" | sed -e 's/:.*$//' -e 's/^echo //' |
|
||||
awk '{ print $1 }' | grep -v '\.' | wc -l`"
|
||||
echo Total number of builds: $nbuilds
|
||||
nbatches="`grep 'Start batch' $T/script | grep -v ">>" | wc -l`"
|
||||
echo Total number of batches: $nbatches
|
||||
exit 0
|
||||
elif test "$dryrun" = batches
|
||||
then
|
||||
# Extract the tests and their batches from the script.
|
||||
egrep 'Start batch|Starting build\.' $T/script | grep -v ">>" |
|
||||
sed -e 's/:.*$//' -e 's/^echo //' -e 's/-ovf//' |
|
||||
awk '
|
||||
/^----Start/ {
|
||||
batchno = $3;
|
||||
next;
|
||||
}
|
||||
{
|
||||
print batchno, $1, $2
|
||||
}'
|
||||
else
|
||||
# Not a dryrun, so run the script.
|
||||
sh $T/script
|
||||
bash $T/script
|
||||
ret=$?
|
||||
echo " --- Done at `date` (`get_starttime_duration $starttime`) exitcode $ret" | tee -a $resdir/$ds/log
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
# 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
|
||||
|
||||
@@ -21,7 +21,7 @@ mkdir $T
|
||||
|
||||
. functions.sh
|
||||
|
||||
if grep -q CC < $F || test -n "$TORTURE_TRUST_MAKE"
|
||||
if grep -q CC < $F || test -n "$TORTURE_TRUST_MAKE" || grep -qe --trust-make < `dirname $F`/../log
|
||||
then
|
||||
:
|
||||
else
|
||||
|
||||
@@ -128,7 +128,7 @@ then
|
||||
then
|
||||
summary="$summary Badness: $n_badness"
|
||||
fi
|
||||
n_warn=`grep -v 'Warning: unable to open an initial console' $file | egrep -c 'WARNING:|Warn'`
|
||||
n_warn=`grep -v 'Warning: unable to open an initial console' $file | grep -v 'Warning: Failed to add ttynull console. No stdin, stdout, and stderr for the init process' | egrep -c 'WARNING:|Warn'`
|
||||
if test "$n_warn" -ne 0
|
||||
then
|
||||
summary="$summary Warnings: $n_warn"
|
||||
|
||||
+442
@@ -0,0 +1,442 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Run a series of torture tests, intended for overnight or
|
||||
# longer timeframes, and also for large systems.
|
||||
#
|
||||
# Usage: torture.sh [ options ]
|
||||
#
|
||||
# Copyright (C) 2020 Facebook, Inc.
|
||||
#
|
||||
# Authors: Paul E. McKenney <paulmck@kernel.org>
|
||||
|
||||
scriptname=$0
|
||||
args="$*"
|
||||
|
||||
KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
|
||||
PATH=${KVM}/bin:$PATH; export PATH
|
||||
. functions.sh
|
||||
|
||||
TORTURE_ALLOTED_CPUS="`identify_qemu_vcpus`"
|
||||
MAKE_ALLOTED_CPUS=$((TORTURE_ALLOTED_CPUS*2))
|
||||
HALF_ALLOTED_CPUS=$((TORTURE_ALLOTED_CPUS/2))
|
||||
if test "$HALF_ALLOTED_CPUS" -lt 1
|
||||
then
|
||||
HALF_ALLOTED_CPUS=1
|
||||
fi
|
||||
VERBOSE_BATCH_CPUS=$((TORTURE_ALLOTED_CPUS/16))
|
||||
if test "$VERBOSE_BATCH_CPUS" -lt 2
|
||||
then
|
||||
VERBOSE_BATCH_CPUS=0
|
||||
fi
|
||||
|
||||
# Configurations/scenarios.
|
||||
configs_rcutorture=
|
||||
configs_locktorture=
|
||||
configs_scftorture=
|
||||
kcsan_kmake_args=
|
||||
|
||||
# Default compression, duration, and apportionment.
|
||||
compress_kasan_vmlinux="`identify_qemu_vcpus`"
|
||||
duration_base=10
|
||||
duration_rcutorture_frac=7
|
||||
duration_locktorture_frac=1
|
||||
duration_scftorture_frac=2
|
||||
|
||||
# "yes" or "no" parameters
|
||||
do_allmodconfig=yes
|
||||
do_rcutorture=yes
|
||||
do_locktorture=yes
|
||||
do_scftorture=yes
|
||||
do_rcuscale=yes
|
||||
do_refscale=yes
|
||||
do_kvfree=yes
|
||||
do_kasan=yes
|
||||
do_kcsan=no
|
||||
|
||||
# doyesno - Helper function for yes/no arguments
|
||||
function doyesno () {
|
||||
if test "$1" = "$2"
|
||||
then
|
||||
echo yes
|
||||
else
|
||||
echo no
|
||||
fi
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo "Usage: $scriptname optional arguments:"
|
||||
echo " --compress-kasan-vmlinux concurrency"
|
||||
echo " --configs-rcutorture \"config-file list w/ repeat factor (3*TINY01)\""
|
||||
echo " --configs-locktorture \"config-file list w/ repeat factor (10*LOCK01)\""
|
||||
echo " --configs-scftorture \"config-file list w/ repeat factor (2*CFLIST)\""
|
||||
echo " --doall"
|
||||
echo " --doallmodconfig / --do-no-allmodconfig"
|
||||
echo " --do-kasan / --do-no-kasan"
|
||||
echo " --do-kcsan / --do-no-kcsan"
|
||||
echo " --do-kvfree / --do-no-kvfree"
|
||||
echo " --do-locktorture / --do-no-locktorture"
|
||||
echo " --do-none"
|
||||
echo " --do-rcuscale / --do-no-rcuscale"
|
||||
echo " --do-rcutorture / --do-no-rcutorture"
|
||||
echo " --do-refscale / --do-no-refscale"
|
||||
echo " --do-scftorture / --do-no-scftorture"
|
||||
echo " --duration [ <minutes> | <hours>h | <days>d ]"
|
||||
echo " --kcsan-kmake-arg kernel-make-arguments"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while test $# -gt 0
|
||||
do
|
||||
case "$1" in
|
||||
--compress-kasan-vmlinux)
|
||||
checkarg --compress-kasan-vmlinux "(concurrency level)" $# "$2" '^[0-9][0-9]*$' '^error'
|
||||
compress_kasan_vmlinux=$2
|
||||
shift
|
||||
;;
|
||||
--config-rcutorture|--configs-rcutorture)
|
||||
checkarg --configs-rcutorture "(list of config files)" "$#" "$2" '^[^/]\+$' '^--'
|
||||
configs_rcutorture="$configs_rcutorture $2"
|
||||
shift
|
||||
;;
|
||||
--config-locktorture|--configs-locktorture)
|
||||
checkarg --configs-locktorture "(list of config files)" "$#" "$2" '^[^/]\+$' '^--'
|
||||
configs_locktorture="$configs_locktorture $2"
|
||||
shift
|
||||
;;
|
||||
--config-scftorture|--configs-scftorture)
|
||||
checkarg --configs-scftorture "(list of config files)" "$#" "$2" '^[^/]\+$' '^--'
|
||||
configs_scftorture="$configs_scftorture $2"
|
||||
shift
|
||||
;;
|
||||
--doall)
|
||||
do_allmodconfig=yes
|
||||
do_rcutorture=yes
|
||||
do_locktorture=yes
|
||||
do_scftorture=yes
|
||||
do_rcuscale=yes
|
||||
do_refscale=yes
|
||||
do_kvfree=yes
|
||||
do_kasan=yes
|
||||
do_kcsan=yes
|
||||
;;
|
||||
--do-allmodconfig|--do-no-allmodconfig)
|
||||
do_allmodconfig=`doyesno "$1" --do-allmodconfig`
|
||||
;;
|
||||
--do-kasan|--do-no-kasan)
|
||||
do_kasan=`doyesno "$1" --do-kasan`
|
||||
;;
|
||||
--do-kcsan|--do-no-kcsan)
|
||||
do_kcsan=`doyesno "$1" --do-kcsan`
|
||||
;;
|
||||
--do-kvfree|--do-no-kvfree)
|
||||
do_kvfree=`doyesno "$1" --do-kvfree`
|
||||
;;
|
||||
--do-locktorture|--do-no-locktorture)
|
||||
do_locktorture=`doyesno "$1" --do-locktorture`
|
||||
;;
|
||||
--do-none)
|
||||
do_allmodconfig=no
|
||||
do_rcutorture=no
|
||||
do_locktorture=no
|
||||
do_scftorture=no
|
||||
do_rcuscale=no
|
||||
do_refscale=no
|
||||
do_kvfree=no
|
||||
do_kasan=no
|
||||
do_kcsan=no
|
||||
;;
|
||||
--do-rcuscale|--do-no-rcuscale)
|
||||
do_rcuscale=`doyesno "$1" --do-rcuscale`
|
||||
;;
|
||||
--do-rcutorture|--do-no-rcutorture)
|
||||
do_rcutorture=`doyesno "$1" --do-rcutorture`
|
||||
;;
|
||||
--do-refscale|--do-no-refscale)
|
||||
do_refscale=`doyesno "$1" --do-refscale`
|
||||
;;
|
||||
--do-scftorture|--do-no-scftorture)
|
||||
do_scftorture=`doyesno "$1" --do-scftorture`
|
||||
;;
|
||||
--duration)
|
||||
checkarg --duration "(minutes)" $# "$2" '^[0-9][0-9]*\(m\|h\|d\|\)$' '^error'
|
||||
mult=1
|
||||
if echo "$2" | grep -q 'm$'
|
||||
then
|
||||
mult=1
|
||||
elif echo "$2" | grep -q 'h$'
|
||||
then
|
||||
mult=60
|
||||
elif echo "$2" | grep -q 'd$'
|
||||
then
|
||||
mult=1440
|
||||
fi
|
||||
ts=`echo $2 | sed -e 's/[smhd]$//'`
|
||||
duration_base=$(($ts*mult))
|
||||
shift
|
||||
;;
|
||||
--kcsan-kmake-arg|--kcsan-kmake-args)
|
||||
checkarg --kcsan-kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
|
||||
kcsan_kmake_args="`echo "$kcsan_kmake_args $2" | sed -e 's/^ *//' -e 's/ *$//'`"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo Unknown argument $1
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
ds="`date +%Y.%m.%d-%H.%M.%S`-torture"
|
||||
startdate="`date`"
|
||||
starttime="`get_starttime`"
|
||||
|
||||
T=/tmp/torture.sh.$$
|
||||
trap 'rm -rf $T' 0 2
|
||||
mkdir $T
|
||||
|
||||
echo " --- " $scriptname $args | tee -a $T/log
|
||||
echo " --- Results directory: " $ds | tee -a $T/log
|
||||
|
||||
# Calculate rcutorture defaults and apportion time
|
||||
if test -z "$configs_rcutorture"
|
||||
then
|
||||
configs_rcutorture=CFLIST
|
||||
fi
|
||||
duration_rcutorture=$((duration_base*duration_rcutorture_frac/10))
|
||||
if test "$duration_rcutorture" -eq 0
|
||||
then
|
||||
echo " --- Zero time for rcutorture, disabling" | tee -a $T/log
|
||||
do_rcutorture=no
|
||||
fi
|
||||
|
||||
# Calculate locktorture defaults and apportion time
|
||||
if test -z "$configs_locktorture"
|
||||
then
|
||||
configs_locktorture=CFLIST
|
||||
fi
|
||||
duration_locktorture=$((duration_base*duration_locktorture_frac/10))
|
||||
if test "$duration_locktorture" -eq 0
|
||||
then
|
||||
echo " --- Zero time for locktorture, disabling" | tee -a $T/log
|
||||
do_locktorture=no
|
||||
fi
|
||||
|
||||
# Calculate scftorture defaults and apportion time
|
||||
if test -z "$configs_scftorture"
|
||||
then
|
||||
configs_scftorture=CFLIST
|
||||
fi
|
||||
duration_scftorture=$((duration_base*duration_scftorture_frac/10))
|
||||
if test "$duration_scftorture" -eq 0
|
||||
then
|
||||
echo " --- Zero time for scftorture, disabling" | tee -a $T/log
|
||||
do_scftorture=no
|
||||
fi
|
||||
|
||||
touch $T/failures
|
||||
touch $T/successes
|
||||
|
||||
# torture_one - Does a single kvm.sh run.
|
||||
#
|
||||
# Usage:
|
||||
# torture_bootargs="[ kernel boot arguments ]"
|
||||
# torture_one flavor [ kvm.sh arguments ]
|
||||
#
|
||||
# Note that "flavor" is an arbitrary string. Supply --torture if needed.
|
||||
# Note that quoting is problematic. So on the command line, pass multiple
|
||||
# values with multiple kvm.sh argument instances.
|
||||
function torture_one {
|
||||
local cur_bootargs=
|
||||
local boottag=
|
||||
|
||||
echo " --- $curflavor:" Start `date` | tee -a $T/log
|
||||
if test -n "$torture_bootargs"
|
||||
then
|
||||
boottag="--bootargs"
|
||||
cur_bootargs="$torture_bootargs"
|
||||
fi
|
||||
"$@" $boottag "$cur_bootargs" --datestamp "$ds/results-$curflavor" > $T/$curflavor.out 2>&1
|
||||
retcode=$?
|
||||
resdir="`grep '^Results directory: ' $T/$curflavor.out | tail -1 | sed -e 's/^Results directory: //'`"
|
||||
if test -z "$resdir"
|
||||
then
|
||||
cat $T/$curflavor.out | tee -a $T/log
|
||||
echo retcode=$retcode | tee -a $T/log
|
||||
fi
|
||||
if test "$retcode" == 0
|
||||
then
|
||||
echo "$curflavor($retcode)" $resdir >> $T/successes
|
||||
else
|
||||
echo "$curflavor($retcode)" $resdir >> $T/failures
|
||||
fi
|
||||
}
|
||||
|
||||
# torture_set - Does a set of tortures with and without KASAN and KCSAN.
|
||||
#
|
||||
# Usage:
|
||||
# torture_bootargs="[ kernel boot arguments ]"
|
||||
# torture_set flavor [ kvm.sh arguments ]
|
||||
#
|
||||
# Note that "flavor" is an arbitrary string. Supply --torture if needed.
|
||||
# Note that quoting is problematic. So on the command line, pass multiple
|
||||
# values with multiple kvm.sh argument instances.
|
||||
function torture_set {
|
||||
local cur_kcsan_kmake_args=
|
||||
local kcsan_kmake_tag=
|
||||
local flavor=$1
|
||||
shift
|
||||
curflavor=$flavor
|
||||
torture_one "$@"
|
||||
if test "$do_kasan" = "yes"
|
||||
then
|
||||
curflavor=${flavor}-kasan
|
||||
torture_one "$@" --kasan
|
||||
fi
|
||||
if test "$do_kcsan" = "yes"
|
||||
then
|
||||
curflavor=${flavor}-kcsan
|
||||
if test -n "$kcsan_kmake_args"
|
||||
then
|
||||
kcsan_kmake_tag="--kmake-args"
|
||||
cur_kcsan_kmake_args="$kcsan_kmake_args"
|
||||
fi
|
||||
torture_one $* --kconfig "CONFIG_DEBUG_LOCK_ALLOC=y CONFIG_PROVE_LOCKING=y" $kcsan_kmake_tag $cur_kcsan_kmake_args --kcsan
|
||||
fi
|
||||
}
|
||||
|
||||
# make allmodconfig
|
||||
if test "$do_allmodconfig" = "yes"
|
||||
then
|
||||
echo " --- allmodconfig:" Start `date` | tee -a $T/log
|
||||
amcdir="tools/testing/selftests/rcutorture/res/$ds/allmodconfig"
|
||||
mkdir -p "$amcdir"
|
||||
echo " --- make clean" > "$amcdir/Make.out" 2>&1
|
||||
make -j$MAKE_ALLOTED_CPUS clean >> "$amcdir/Make.out" 2>&1
|
||||
echo " --- make allmodconfig" >> "$amcdir/Make.out" 2>&1
|
||||
make -j$MAKE_ALLOTED_CPUS allmodconfig >> "$amcdir/Make.out" 2>&1
|
||||
echo " --- make " >> "$amcdir/Make.out" 2>&1
|
||||
make -j$MAKE_ALLOTED_CPUS >> "$amcdir/Make.out" 2>&1
|
||||
retcode="$?"
|
||||
echo $retcode > "$amcdir/Make.exitcode"
|
||||
if test "$retcode" == 0
|
||||
then
|
||||
echo "allmodconfig($retcode)" $amcdir >> $T/successes
|
||||
else
|
||||
echo "allmodconfig($retcode)" $amcdir >> $T/failures
|
||||
fi
|
||||
fi
|
||||
|
||||
# --torture rcu
|
||||
if test "$do_rcutorture" = "yes"
|
||||
then
|
||||
torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000"
|
||||
torture_set "rcutorture" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration "$duration_rcutorture" --configs "$configs_rcutorture" --trust-make
|
||||
fi
|
||||
|
||||
if test "$do_locktorture" = "yes"
|
||||
then
|
||||
torture_bootargs="torture.disable_onoff_at_boot"
|
||||
torture_set "locktorture" tools/testing/selftests/rcutorture/bin/kvm.sh --torture lock --allcpus --duration "$duration_locktorture" --configs "$configs_locktorture" --trust-make
|
||||
fi
|
||||
|
||||
if test "$do_scftorture" = "yes"
|
||||
then
|
||||
torture_bootargs="scftorture.nthreads=$HALF_ALLOTED_CPUS torture.disable_onoff_at_boot"
|
||||
torture_set "scftorture" tools/testing/selftests/rcutorture/bin/kvm.sh --torture scf --allcpus --duration "$duration_scftorture" --configs "$configs_scftorture" --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --trust-make
|
||||
fi
|
||||
|
||||
if test "$do_refscale" = yes
|
||||
then
|
||||
primlist="`grep '\.name[ ]*=' kernel/rcu/refscale.c | sed -e 's/^[^"]*"//' -e 's/".*$//'`"
|
||||
else
|
||||
primlist=
|
||||
fi
|
||||
for prim in $primlist
|
||||
do
|
||||
torture_bootargs="refscale.scale_type="$prim" refscale.nreaders=$HALF_ALLOTED_CPUS refscale.loops=10000 refscale.holdoff=20 torture.disable_onoff_at_boot"
|
||||
torture_set "refscale-$prim" tools/testing/selftests/rcutorture/bin/kvm.sh --torture refscale --allcpus --duration 5 --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --bootargs "verbose_batched=$VERBOSE_BATCH_CPUS torture.verbose_sleep_frequency=8 torture.verbose_sleep_duration=$VERBOSE_BATCH_CPUS" --trust-make
|
||||
done
|
||||
|
||||
if test "$do_rcuscale" = yes
|
||||
then
|
||||
primlist="`grep '\.name[ ]*=' kernel/rcu/rcuscale.c | sed -e 's/^[^"]*"//' -e 's/".*$//'`"
|
||||
else
|
||||
primlist=
|
||||
fi
|
||||
for prim in $primlist
|
||||
do
|
||||
torture_bootargs="rcuscale.scale_type="$prim" rcuscale.nwriters=$HALF_ALLOTED_CPUS rcuscale.holdoff=20 torture.disable_onoff_at_boot"
|
||||
torture_set "rcuscale-$prim" tools/testing/selftests/rcutorture/bin/kvm.sh --torture rcuscale --allcpus --duration 5 --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --trust-make
|
||||
done
|
||||
|
||||
if test "$do_kvfree" = "yes"
|
||||
then
|
||||
torture_bootargs="rcuscale.kfree_rcu_test=1 rcuscale.kfree_nthreads=16 rcuscale.holdoff=20 rcuscale.kfree_loops=10000 torture.disable_onoff_at_boot"
|
||||
torture_set "rcuscale-kvfree" tools/testing/selftests/rcutorture/bin/kvm.sh --torture rcuscale --allcpus --duration 10 --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --trust-make
|
||||
fi
|
||||
|
||||
echo " --- " $scriptname $args
|
||||
echo " --- " Done `date` | tee -a $T/log
|
||||
ret=0
|
||||
nsuccesses=0
|
||||
echo SUCCESSES: | tee -a $T/log
|
||||
if test -s "$T/successes"
|
||||
then
|
||||
cat "$T/successes" | tee -a $T/log
|
||||
nsuccesses="`wc -l "$T/successes" | awk '{ print $1 }'`"
|
||||
fi
|
||||
nfailures=0
|
||||
echo FAILURES: | tee -a $T/log
|
||||
if test -s "$T/failures"
|
||||
then
|
||||
cat "$T/failures" | tee -a $T/log
|
||||
nfailures="`wc -l "$T/failures" | awk '{ print $1 }'`"
|
||||
ret=2
|
||||
fi
|
||||
echo Started at $startdate, ended at `date`, duration `get_starttime_duration $starttime`. | tee -a $T/log
|
||||
echo Summary: Successes: $nsuccesses Failures: $nfailures. | tee -a $T/log
|
||||
tdir="`cat $T/successes $T/failures | head -1 | awk '{ print $NF }' | sed -e 's,/[^/]\+/*$,,'`"
|
||||
if test -n "$tdir" && test $compress_kasan_vmlinux -gt 0
|
||||
then
|
||||
# KASAN vmlinux files can approach 1GB in size, so compress them.
|
||||
echo Looking for KASAN files to compress: `date` > "$tdir/log-xz" 2>&1
|
||||
find "$tdir" -type d -name '*-kasan' -print > $T/xz-todo
|
||||
ncompresses=0
|
||||
batchno=1
|
||||
if test -s $T/xz-todo
|
||||
then
|
||||
echo Size before compressing: `du -sh $tdir | awk '{ print $1 }'` `date` 2>&1 | tee -a "$tdir/log-xz" | tee -a $T/log
|
||||
for i in `cat $T/xz-todo`
|
||||
do
|
||||
echo Compressing vmlinux files in ${i}: `date` >> "$tdir/log-xz" 2>&1
|
||||
for j in $i/*/vmlinux
|
||||
do
|
||||
xz "$j" >> "$tdir/log-xz" 2>&1 &
|
||||
ncompresses=$((ncompresses+1))
|
||||
if test $ncompresses -ge $compress_kasan_vmlinux
|
||||
then
|
||||
echo Waiting for batch $batchno of $ncompresses compressions `date` | tee -a "$tdir/log-xz" | tee -a $T/log
|
||||
wait
|
||||
ncompresses=0
|
||||
batchno=$((batchno+1))
|
||||
fi
|
||||
done
|
||||
done
|
||||
if test $ncompresses -gt 0
|
||||
then
|
||||
echo Waiting for final batch $batchno of $ncompresses compressions `date` | tee -a "$tdir/log-xz" | tee -a $T/log
|
||||
fi
|
||||
wait
|
||||
echo Size after compressing: `du -sh $tdir | awk '{ print $1 }'` `date` 2>&1 | tee -a "$tdir/log-xz" | tee -a $T/log
|
||||
echo Total duration `get_starttime_duration $starttime`. | tee -a $T/log
|
||||
else
|
||||
echo No compression needed: `date` >> "$tdir/log-xz" 2>&1
|
||||
fi
|
||||
fi
|
||||
if test -n "$tdir"
|
||||
then
|
||||
cp $T/log "$tdir"
|
||||
fi
|
||||
exit $ret
|
||||
@@ -1 +1,2 @@
|
||||
rcutorture.torture_type=tasks-rude
|
||||
rcutree.use_softirq=0
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
rcutorture.torture_type=tasks
|
||||
rcutree.use_softirq=0
|
||||
|
||||
@@ -2,5 +2,7 @@ maxcpus=8 nr_cpus=43
|
||||
rcutree.gp_preinit_delay=3
|
||||
rcutree.gp_init_delay=3
|
||||
rcutree.gp_cleanup_delay=3
|
||||
rcu_nocbs=0
|
||||
rcu_nocbs=0-1,3-7
|
||||
rcutorture.nocbs_nthreads=8
|
||||
rcutorture.nocbs_toggle=1000
|
||||
rcutorture.fwd_progress=0
|
||||
|
||||
Reference in New Issue
Block a user