From dc16b678840266ca372e93acc29b263ce29b6a77 Mon Sep 17 00:00:00 2001 From: Tony Hutter Date: Wed, 23 Mar 2022 08:15:02 -0700 Subject: [PATCH] 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 Signed-off-by: Tony Hutter Closes #13227 --- scripts/zfs-tests.sh | 9 ++++++- tests/test-runner/bin/test-runner.py.in | 33 ++++++++++++++++++------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/scripts/zfs-tests.sh b/scripts/zfs-tests.sh index 2477d0f91799..851ff8b74e52 100755 --- a/scripts/zfs-tests.sh +++ b/scripts/zfs-tests.sh @@ -39,6 +39,7 @@ VERBOSE="no" QUIET="" CLEANUP="yes" CLEANUPALL="no" +KMSG="" LOOPBACK="yes" STACK_TRACER="no" FILESIZE="4G" @@ -326,6 +327,7 @@ OPTIONS: -q Quiet test-runner output -x Remove all testpools, dm, lo, and files (unsafe) -k Disable cleanup after test failure + -K Log test names to /dev/kmsg -f Use files only, disables block device tests -S Enable stack tracer (negative performance impact) -c Only create and populate constrained path @@ -357,7 +359,7 @@ $0 -x 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 h) usage @@ -375,6 +377,9 @@ while getopts 'hvqxkfScRmn:d:s:r:?t:T:u:I:' OPTION; do k) CLEANUP="no" ;; + K) + KMSG="yes" + ;; f) LOOPBACK="no" ;; @@ -705,6 +710,7 @@ REPORT_FILE=$(mktemp_file zts-report) msg "${TEST_RUNNER}" \ "${QUIET:+-q}" \ "${KMEMLEAK:+-m}" \ + "${KMSG:+-K}" \ "-c \"${RUNFILES}\"" \ "-T \"${TAGS}\"" \ "-i \"${STF_SUITE}\"" \ @@ -712,6 +718,7 @@ msg "${TEST_RUNNER}" \ { ${TEST_RUNNER} \ ${QUIET:+-q} \ ${KMEMLEAK:+-m} \ + ${KMSG:+-K} \ -c "${RUNFILES}" \ -T "${TAGS}" \ -i "${STF_SUITE}" \ diff --git a/tests/test-runner/bin/test-runner.py.in b/tests/test-runner/bin/test-runner.py.in index c644745b4390..5c868d945a8c 100755 --- a/tests/test-runner/bin/test-runner.py.in +++ b/tests/test-runner/bin/test-runner.py.in @@ -34,6 +34,7 @@ from subprocess import Popen from subprocess import check_output from threading import Timer from time import time, CLOCK_MONOTONIC +from os.path import exists BASEDIR = '/var/tmp/test_results' TESTDIR = '/usr/share/zfs/' @@ -256,7 +257,7 @@ User: %s 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. Determine whether or not the command requires sudo, and modify it @@ -275,6 +276,18 @@ User: %s except OSError as 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() if kmemleak: @@ -459,14 +472,14 @@ Tags: %s cont = True if len(pretest.pathname): - pretest.run(options.dryrun, False) + pretest.run(options.dryrun, False, options.kmsg) cont = pretest.result.result == 'PASS' pretest.log(options) 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): - failsafe.run(options.dryrun, False) + failsafe.run(options.dryrun, False, options.kmsg) failsafe.log(options, suppress_console=True) else: test.skip() @@ -474,7 +487,7 @@ Tags: %s test.log(options) if len(posttest.pathname): - posttest.run(options.dryrun, False) + posttest.run(options.dryrun, False, options.kmsg) posttest.log(options) @@ -577,7 +590,7 @@ Tags: %s cont = True if len(pretest.pathname): - pretest.run(options.dryrun, False) + pretest.run(options.dryrun, False, options.kmsg) cont = pretest.result.result == 'PASS' pretest.log(options) @@ -590,9 +603,9 @@ Tags: %s failsafe = Cmd(self.failsafe, outputdir=odir, timeout=self.timeout, user=self.failsafe_user, identifier=self.identifier) 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): - failsafe.run(options.dryrun, False) + failsafe.run(options.dryrun, False, options.kmsg) failsafe.log(options, suppress_console=True) else: test.skip() @@ -600,7 +613,7 @@ Tags: %s test.log(options) if len(posttest.pathname): - posttest.run(options.dryrun, False) + posttest.run(options.dryrun, False, options.kmsg) posttest.log(options) @@ -1060,6 +1073,8 @@ def parse_args(): parser.add_option('-i', action='callback', callback=options_cb, default=TESTDIR, dest='testdir', type='string', 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, default=False, dest='kmemleak', help='Enable kmemleak reporting (Linux only)')