ZTS: Log test name to /dev/kmsg on Linux

Add a -K option to the test suite to log each test name to /dev/kmsg
(on Linux), so if there's a kernel warning we'll be able to match
it up to a particular test.

Reviewed-by: John Kennedy <john.kennedy@delphix.com>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes  #13227
This commit is contained in:
Tony Hutter 2022-03-23 08:15:02 -07:00
parent a69765ea5b
commit fc2c0256c5
2 changed files with 32 additions and 10 deletions

View File

@ -38,6 +38,7 @@ VERBOSE="no"
QUIET="" QUIET=""
CLEANUP="yes" CLEANUP="yes"
CLEANUPALL="no" CLEANUPALL="no"
KMSG=""
LOOPBACK="yes" LOOPBACK="yes"
STACK_TRACER="no" STACK_TRACER="no"
FILESIZE="4G" FILESIZE="4G"
@ -325,6 +326,7 @@ OPTIONS:
-q Quiet test-runner output -q Quiet test-runner output
-x Remove all testpools, dm, lo, and files (unsafe) -x Remove all testpools, dm, lo, and files (unsafe)
-k Disable cleanup after test failure -k Disable cleanup after test failure
-K Log test names to /dev/kmsg
-f Use files only, disables block device tests -f Use files only, disables block device tests
-S Enable stack tracer (negative performance impact) -S Enable stack tracer (negative performance impact)
-c Only create and populate constrained path -c Only create and populate constrained path
@ -356,7 +358,7 @@ $0 -x
EOF EOF
} }
while getopts 'hvqxkfScRmn:d:s:r:?t:T:u:I:' OPTION; do while getopts 'hvqxkKfScRmn:d:s:r:?t:T:u:I:' OPTION; do
case $OPTION in case $OPTION in
h) h)
usage usage
@ -374,6 +376,9 @@ while getopts 'hvqxkfScRmn:d:s:r:?t:T:u:I:' OPTION; do
k) k)
CLEANUP="no" CLEANUP="no"
;; ;;
K)
KMSG="yes"
;;
f) f)
LOOPBACK="no" LOOPBACK="no"
;; ;;
@ -702,11 +707,13 @@ REPORT_FILE=$(mktemp_file zts-report)
msg "${TEST_RUNNER}" \ msg "${TEST_RUNNER}" \
"${QUIET:+-q}" \ "${QUIET:+-q}" \
"${KMEMLEAK:+-m}" \ "${KMEMLEAK:+-m}" \
"${KMSG:+-K}" \
"-c \"${RUNFILES}\"" \ "-c \"${RUNFILES}\"" \
"-T \"${TAGS}\"" \ "-T \"${TAGS}\"" \
"-i \"${STF_SUITE}\"" \ "-i \"${STF_SUITE}\"" \
"-I \"${ITERATIONS}\"" "-I \"${ITERATIONS}\""
${TEST_RUNNER} ${QUIET:+-q} ${KMEMLEAK:+-m} \ ${TEST_RUNNER} ${QUIET:+-q} ${KMEMLEAK:+-m} \
${KMSG:+-K} \
-c "${RUNFILES}" \ -c "${RUNFILES}" \
-T "${TAGS}" \ -T "${TAGS}" \
-i "${STF_SUITE}" \ -i "${STF_SUITE}" \

View File

@ -39,6 +39,7 @@ from subprocess import Popen
from subprocess import check_output from subprocess import check_output
from threading import Timer from threading import Timer
from time import time from time import time
from os.path import exists
BASEDIR = '/var/tmp/test_results' BASEDIR = '/var/tmp/test_results'
TESTDIR = '/usr/share/zfs/' TESTDIR = '/usr/share/zfs/'
@ -264,7 +265,7 @@ User: %s
return out.lines, err.lines return out.lines, err.lines
def run(self, dryrun, kmemleak): def run(self, dryrun, kmemleak, kmsg):
""" """
This is the main function that runs each individual test. This is the main function that runs each individual test.
Determine whether or not the command requires sudo, and modify it Determine whether or not the command requires sudo, and modify it
@ -283,6 +284,18 @@ User: %s
except OSError as e: except OSError as e:
fail('%s' % e) fail('%s' % e)
"""
Log each test we run to /dev/kmsg (on Linux), so if there's a kernel
warning we'll be able to match it up to a particular test.
"""
if kmsg is True and exists("/dev/kmsg"):
try:
kp = Popen([SUDO, "sh", "-c",
f"echo ZTS run {self.pathname} > /dev/kmsg"])
kp.wait()
except Exception:
pass
self.result.starttime = monotonic_time() self.result.starttime = monotonic_time()
if kmemleak: if kmemleak:
@ -467,14 +480,14 @@ Tags: %s
cont = True cont = True
if len(pretest.pathname): if len(pretest.pathname):
pretest.run(options.dryrun, False) pretest.run(options.dryrun, False, options.kmsg)
cont = pretest.result.result == 'PASS' cont = pretest.result.result == 'PASS'
pretest.log(options) pretest.log(options)
if cont: if cont:
test.run(options.dryrun, options.kmemleak) test.run(options.dryrun, options.kmemleak, options.kmsg)
if test.result.result == 'KILLED' and len(failsafe.pathname): if test.result.result == 'KILLED' and len(failsafe.pathname):
failsafe.run(options.dryrun, False) failsafe.run(options.dryrun, False, options.kmsg)
failsafe.log(options, suppress_console=True) failsafe.log(options, suppress_console=True)
else: else:
test.skip() test.skip()
@ -482,7 +495,7 @@ Tags: %s
test.log(options) test.log(options)
if len(posttest.pathname): if len(posttest.pathname):
posttest.run(options.dryrun, False) posttest.run(options.dryrun, False, options.kmsg)
posttest.log(options) posttest.log(options)
@ -585,7 +598,7 @@ Tags: %s
cont = True cont = True
if len(pretest.pathname): if len(pretest.pathname):
pretest.run(options.dryrun, False) pretest.run(options.dryrun, False, options.kmsg)
cont = pretest.result.result == 'PASS' cont = pretest.result.result == 'PASS'
pretest.log(options) pretest.log(options)
@ -598,9 +611,9 @@ Tags: %s
failsafe = Cmd(self.failsafe, outputdir=odir, timeout=self.timeout, failsafe = Cmd(self.failsafe, outputdir=odir, timeout=self.timeout,
user=self.failsafe_user, identifier=self.identifier) user=self.failsafe_user, identifier=self.identifier)
if cont: if cont:
test.run(options.dryrun, options.kmemleak) test.run(options.dryrun, options.kmemleak, options.kmsg)
if test.result.result == 'KILLED' and len(failsafe.pathname): if test.result.result == 'KILLED' and len(failsafe.pathname):
failsafe.run(options.dryrun, False) failsafe.run(options.dryrun, False, options.kmsg)
failsafe.log(options, suppress_console=True) failsafe.log(options, suppress_console=True)
else: else:
test.skip() test.skip()
@ -608,7 +621,7 @@ Tags: %s
test.log(options) test.log(options)
if len(posttest.pathname): if len(posttest.pathname):
posttest.run(options.dryrun, False) posttest.run(options.dryrun, False, options.kmsg)
posttest.log(options) posttest.log(options)
@ -1068,6 +1081,8 @@ def parse_args():
parser.add_option('-i', action='callback', callback=options_cb, parser.add_option('-i', action='callback', callback=options_cb,
default=TESTDIR, dest='testdir', type='string', default=TESTDIR, dest='testdir', type='string',
metavar='testdir', help='Specify a test directory.') metavar='testdir', help='Specify a test directory.')
parser.add_option('-K', action='store_true', default=False, dest='kmsg',
help='Log tests names to /dev/kmsg')
parser.add_option('-m', action='callback', callback=kmemleak_cb, parser.add_option('-m', action='callback', callback=kmemleak_cb,
default=False, dest='kmemleak', default=False, dest='kmemleak',
help='Enable kmemleak reporting (Linux only)') help='Enable kmemleak reporting (Linux only)')