Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <nfraprado@collabora.com>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20240705-dev-err-log-selftest-v2-3-163b9cd7b3c1@collabora.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Nícolas F. R. A. Prado and committed by
Greg Kroah-Hartman
b7274930 0e7b7bde

+89
+1
tools/testing/selftests/Makefile
··· 13 13 TARGETS += cpufreq 14 14 TARGETS += cpu-hotplug 15 15 TARGETS += damon 16 + TARGETS += devices/error_logs 16 17 TARGETS += devices/probe 17 18 TARGETS += dmabuf-heaps 18 19 TARGETS += drivers/dma-buf
+3
tools/testing/selftests/devices/error_logs/Makefile
··· 1 + TEST_PROGS := test_device_error_logs.py 2 + 3 + include ../../lib.mk
+85
tools/testing/selftests/devices/error_logs/test_device_error_logs.py
··· 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()