Skip to content

Commit b727493

Browse files
nfrapradogregkh
authored andcommitted
kselftest: devices: Add test to detect device error logs
Log errors are the most widely used mechanism for reporting issues in the kernel. When an error is logged using the device helpers, eg dev_err(), it gets metadata attached that identifies the subsystem and device where the message is coming from. Introduce a new test that makes use of that metadata to report which devices logged errors (or more critical messages). Signed-off-by: Nícolas F. R. A. Prado <[email protected]> Acked-by: Shuah Khan <[email protected]> Acked-by: Greg Kroah-Hartman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 0e7b7bd commit b727493

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

tools/testing/selftests/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ TARGETS += core
1313
TARGETS += cpufreq
1414
TARGETS += cpu-hotplug
1515
TARGETS += damon
16+
TARGETS += devices/error_logs
1617
TARGETS += devices/probe
1718
TARGETS += dmabuf-heaps
1819
TARGETS += drivers/dma-buf
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
TEST_PROGS := test_device_error_logs.py
2+
3+
include ../../lib.mk
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: GPL-2.0
3+
#
4+
# Copyright (c) 2024 Collabora Ltd
5+
#
6+
# This test checks for the presence of error (or more critical) log messages
7+
# coming from devices in the kernel log.
8+
#
9+
# One failed test case is reported for each device that has outputted error
10+
# logs. Devices with no errors do not produce a passing test case to avoid
11+
# polluting the results, therefore a successful run will list 0 tests run.
12+
#
13+
14+
import glob
15+
import os
16+
import re
17+
import sys
18+
19+
# Allow ksft module to be imported from different directory
20+
this_dir = os.path.dirname(os.path.realpath(__file__))
21+
sys.path.append(os.path.join(this_dir, "../../kselftest/"))
22+
23+
import ksft
24+
25+
kmsg = "/dev/kmsg"
26+
27+
RE_log = re.compile(
28+
r"(?P<prefix>[0-9]+),(?P<sequence>[0-9]+),(?P<timestamp>[0-9]+),(?P<flag>[^;]*)(,[^;]*)*;(?P<message>.*)"
29+
)
30+
RE_tag = re.compile(r" (?P<key>[^=]+)=(?P<value>.*)")
31+
32+
PREFIX_ERROR = 3
33+
34+
logs = []
35+
error_log_per_device = {}
36+
37+
38+
def parse_kmsg():
39+
current_log = {}
40+
41+
with open(kmsg) as f:
42+
os.set_blocking(f.fileno(), False)
43+
44+
for line in f:
45+
tag_line = RE_tag.match(line)
46+
log_line = RE_log.match(line)
47+
48+
if log_line:
49+
if current_log:
50+
logs.append(current_log) # Save last log
51+
52+
current_log = {
53+
"prefix": int(log_line.group("prefix")),
54+
"sequence": int(log_line.group("sequence")),
55+
"timestamp": int(log_line.group("timestamp")),
56+
"flag": log_line.group("flag"),
57+
"message": log_line.group("message"),
58+
}
59+
elif tag_line:
60+
current_log[tag_line.group("key")] = tag_line.group("value")
61+
62+
63+
def generate_per_device_error_log():
64+
for log in logs:
65+
if log.get("DEVICE") and log["prefix"] <= PREFIX_ERROR:
66+
if not error_log_per_device.get(log["DEVICE"]):
67+
error_log_per_device[log["DEVICE"]] = []
68+
error_log_per_device[log["DEVICE"]].append(log)
69+
70+
71+
parse_kmsg()
72+
73+
generate_per_device_error_log()
74+
num_tests = len(error_log_per_device)
75+
76+
ksft.print_header()
77+
ksft.set_plan(num_tests)
78+
79+
for device in error_log_per_device:
80+
for log in error_log_per_device[device]:
81+
ksft.print_msg(log["message"])
82+
ksft.test_result_fail(device)
83+
if num_tests == 0:
84+
ksft.print_msg("No device error logs found")
85+
ksft.finished()

0 commit comments

Comments
 (0)