Commit cdeef67d authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

torture: Make kvm.sh select per-scenario affinity masks



This commit causes kvm.sh to use the new kvm-assign-cpus.sh and
kvm-get-cpus-script.sh scripts to create a TORTURE_AFFINITY environment
variable containing either an empty string (for no affinity) or a list
of CPUs to pin the scenario's vCPUs to.  A later commit will make
use of this information to actually pin the vCPUs.

Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent a3d79412
Loading
Loading
Loading
Loading
+106 −0
Original line number Diff line number Diff line
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Produce awk statements roughly depicting the system's CPU and cache
# layout.  If the required information is not available, produce
# error messages as awk comments.  Successful exit regardless.
#
# Usage: kvm-assign-cpus.sh /path/to/sysfs

T=/tmp/kvm-assign-cpus.sh.$$
trap 'rm -rf $T' 0 2
mkdir $T

sysfsdir=${1-/sys/devices/system/node}
if ! cd "$sysfsdir" > $T/msg 2>&1
then
	sed -e 's/^/# /' < $T/msg
	exit 0
fi
nodelist="`ls -d node*`"
for i in node*
do
	if ! test -d $i/
	then
		echo "# Not a directory: $sysfsdir/node*"
		exit 0
	fi
	for j in $i/cpu*/cache/index*
	do
		if ! test -d $j/
		then
			echo "# Not a directory: $sysfsdir/$j"
			exit 0
		else
			break
		fi
	done
	indexlist="`ls -d $i/cpu* | grep 'cpu[0-9][0-9]*' | head -1 | sed -e 's,^.*$,ls -d &/cache/index*,' | sh | sed -e 's,^.*/,,'`"
	break
done
for i in node*/cpu*/cache/index*/shared_cpu_list
do
	if ! test -f $i
	then
		echo "# Not a file: $sysfsdir/$i"
		exit 0
	else
		break
	fi
done
firstshared=
for i in $indexlist
do
	rm -f $T/cpulist
	for n in node*
	do
		f="$n/cpu*/cache/$i/shared_cpu_list"
		if ! cat $f > $T/msg 2>&1
		then
			sed -e 's/^/# /' < $T/msg
			exit 0
		fi
		cat $f >> $T/cpulist
	done
	if grep -q '[-,]' $T/cpulist
	then
		if test -z "$firstshared"
		then
			firstshared="$i"
		fi
	fi
done
if test -z "$firstshared"
then
	splitindex="`echo $indexlist | sed -e 's/ .*$//'`"
else
	splitindex="$firstshared"
fi
nodenum=0
for n in node*
do
	cat $n/cpu*/cache/$splitindex/shared_cpu_list | sort -u -k1n |
	awk -v nodenum="$nodenum" '
	BEGIN {
		idx = 0;
	}

	{
		nlists = split($0, cpulists, ",");
		for (i = 1; i <= nlists; i++) {
			listsize = split(cpulists[i], cpus, "-");
			if (listsize == 1)
				cpus[2] = cpus[1];
			for (j = cpus[1]; j <= cpus[2]; j++) {
				print "cpu[" nodenum "][" idx "] = " j ";";
				idx++;
			}
		}
	}

	END {
		print "nodecpus[" nodenum "] = " idx ";";
	}'
	nodenum=`expr $nodenum + 1`
done
echo "numnodes = $nodenum;"
+88 −0
Original line number Diff line number Diff line
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Create an awk script that takes as input numbers of CPUs and outputs
# lists of CPUs, one per line in both cases.
#
# Usage: kvm-get-cpus-script.sh /path/to/cpu/arrays /path/to/put/script [ /path/to/state ]
#
# The CPU arrays are output by kvm-assign-cpus.sh, and are valid awk
# statements initializing the variables describing the system's topology.
#
# The optional state is input by this script (if the file exists and is
# non-empty), and can also be output by this script.

cpuarrays="${1-/sys/devices/system/node}"
scriptfile="${2}"
statefile="${3}"

if ! test -f "$cpuarrays"
then
	echo "File not found: $cpuarrays" 1>&2
	exit 1
fi
scriptdir="`dirname "$scriptfile"`"
if ! test -d "$scriptdir" || ! test -x "$scriptdir" || ! test -w "$scriptdir"
then
	echo "Directory not usable for script output: $scriptdir"
	exit 1
fi

cat << '___EOF___' > "$scriptfile"
BEGIN {
___EOF___
cat "$cpuarrays" >> "$scriptfile"
if test -r "$statefile"
then
	cat "$statefile" >> "$scriptfile"
fi
cat << '___EOF___' >> "$scriptfile"
}

# Do we have the system architecture to guide CPU affinity?
function gotcpus()
{
	return numnodes != "";
}

# Return a comma-separated list of the next n CPUs.
function nextcpus(n,  i, s)
{
	for (i = 0; i < n; i++) {
		if (nodecpus[curnode] == "")
			curnode = 0;
		if (cpu[curnode][curcpu[curnode]] == "")
			curcpu[curnode] = 0;
		if (s != "")
			s = s ",";
		s = s cpu[curnode][curcpu[curnode]];
		curcpu[curnode]++;
		curnode++
	}
	return s;
}

# Dump out the current node/CPU state so that a later invocation of this
# script can continue where this one left off.  Of course, this only works
# when a state file was specified and where there was valid sysfs state.
# Returns 1 if the state was dumped, 0 otherwise.
#
# Dumping the state for one system configuration and loading it into
# another isn't likely to do what you want, whatever that might be.
function dumpcpustate(  i, fn)
{
___EOF___
echo '	fn = "'"$statefile"'";' >> $scriptfile
cat << '___EOF___' >> "$scriptfile"
	if (fn != "" && gotcpus()) {
		print "curnode = " curnode ";" > fn;
		for (i = 0; i < numnodes; i++)
			if (curcpu[i] != "")
				print "curcpu[" i "] = " curcpu[i] ";" >> fn;
		return 1;
	}
	if (fn != "")
		print "# No CPU state to dump." > fn;
	return 0;
}
___EOF___
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ for i in "$@"
do
	echo ---- System running test: `uname -a` > $i/kvm-test-1-run-qemu.sh.out
	echo > $i/kvm-test-1-run-qemu.sh.out
	export TORTURE_AFFINITY=
	kvm-test-1-run-qemu.sh $i >> $i/kvm-test-1-run-qemu.sh.out 2>&1 &
done
for i in $runfiles
+12 −2
Original line number Diff line number Diff line
@@ -430,7 +430,9 @@ then
	git diff HEAD >> $resdir/$ds/testid.txt
fi
___EOF___
cat << '___EOF___' > $T/dumpbatches.awk
kvm-assign-cpus.sh /sys/devices/system/node > $T/cpuarray.awk
kvm-get-cpus-script.sh $T/cpuarray.awk $T/dumpbatches.awk
cat << '___EOF___' >> $T/dumpbatches.awk
BEGIN {
	i = 0;
}
@@ -442,7 +444,7 @@ BEGIN {
}

# Dump out the scripting required to run one test batch.
function dump(first, pastlast, batchnum)
function dump(first, pastlast, batchnum,  affinitylist)
{
	print "echo ----Start batch " batchnum ": `date` | tee -a " rd "log";
	print "needqemurun="
@@ -474,6 +476,14 @@ function dump(first, pastlast, batchnum)
		print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date` | tee -a " rd "log";
		print "mkdir " rd cfr[jn] " || :";
		print "touch " builddir ".wait";
		affinitylist = "";
		if (gotcpus()) {
			affinitylist = nextcpus(cpusr[jn]);
		}
		if (affinitylist ~ /^[0-9,-][0-9,-]*$/)
			print "export TORTURE_AFFINITY=" affinitylist;
		else
			print "export TORTURE_AFFINITY=";
		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 &"
		print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date` | tee -a " rd "log";
		print "while test -f " builddir ".wait"