[Intel-gfx] [PATCH 1/2] drmtest: introduce kmsg_error functions
Paulo Zanoni
przanoni at gmail.com
Mon Nov 11 18:06:09 CET 2013
From: Paulo Zanoni <paulo.r.zanoni at intel.com>
These functions should help you checking for new Kernel error
messages. One of the problems I had while writing the runtime PM test
suite is that when you read the sysfs and debugfs files, the only way
to detect errors is by checking dmesg, so I was always getting SUCCESS
even if the test caught a bug. Also, we have so many debugfs/sysfs
files that it was not easy to discover which file caused the error
messages I was seeing. So this commit adds some infrastructure to
allow us to automatically check for new errors on dmesg.
Use it like this:
int main(int argc, char *argv[]) {
int fd, i;
igt_fixture
fd = kmsg_error_setup();
igt_subtest("t1") {
kmsg_error_reset(fd);
do_something();
kmsg_error_detect("");
}
igt_subtest("t2") {
for (i = 0; i < 10; i++) {
char *file_name = get_file(i);
kmsg_error_reset(fd);
process_file(file_name);
kmsg_error_detect(file_name):
}
}
igt_fixture
kmsg_error_teardown(fd);
}
Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
---
lib/drmtest.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/drmtest.h | 13 ++++++++++
2 files changed, 92 insertions(+)
diff --git a/lib/drmtest.c b/lib/drmtest.c
index d8fc60f..ebabfd8 100644
--- a/lib/drmtest.c
+++ b/lib/drmtest.c
@@ -41,6 +41,7 @@
#include <linux/kd.h>
#include <unistd.h>
#include <sys/wait.h>
+#include <poll.h>
#include "drm_fourcc.h"
#include "drmtest.h"
@@ -2307,3 +2308,81 @@ void igt_system_suspend_autoresume(void)
ret = system("rtcwake -s 30 -m mem");
igt_assert(ret == 0);
}
+
+/* The kmsg error detecting functions allow you to catch new error messages from
+ * the Kernel. The idea is that you have to call kmsg_error_setup() only once at
+ * the beginning, and kmsg_error_teardown() at the end. And for every subtest,
+ * you run kmsg_error_reset() at the begin and kmsg_error_detect() at the end:
+ * this should make sure that kmsg_error_detect() will only catch the error
+ * messages that were introduced after the subtest started. */
+int kmsg_error_setup(void)
+{
+ int fd = open("/dev/kmsg", O_RDONLY);
+
+ igt_assert_f(fd >= 0, "Can't open /dev/kmsg\n");
+ return fd;
+}
+
+void kmsg_error_teardown(int fd)
+{
+ close(fd);
+}
+
+/* You have to call this before running your subtest, so that the next time you
+ * call kmsg_error_detect you'll only look at the new kmsg lines. */
+void kmsg_error_reset(int fd)
+{
+ lseek(fd, 0, SEEK_END);
+}
+
+static void kmsg_error_line_parse(const char *line, const char *error_msg)
+{
+ igt_assert_f(strstr(line, "------------[ cut here ]------------") == 0,
+ "%s\n", error_msg);
+ igt_assert_f(strstr(line, "*ERROR*") == 0, "%s\n", error_msg);
+ igt_assert_f(strstr(line, "BUG: sleeping function called from invalid context at") == 0,
+ "%s\n", error_msg);
+}
+
+/* Keep reading the Kernel ring buffer and checking for errors. Stop reading if
+ * there's nothing new on the buffer after the timeout. Notice that every time
+ * you call this function, the time it will take to return will always be >= the
+ * timeout. */
+void kmsg_error_detect(int fd, int timeout_ms, const char *error_msg)
+{
+ int i, rc;
+ int line_size = 128, line_used = 0, buf_size = 128;
+ char buf[buf_size];
+ char *line;
+ struct pollfd pfd;
+ ssize_t readed;
+
+ line = malloc(sizeof(char) * line_size);
+ igt_assert(line);
+
+ pfd.fd = fd;
+ pfd.events = POLLIN | POLLPRI;
+
+ while (1) {
+ pfd.revents = 0;
+ rc = poll(&pfd, 1, timeout_ms);
+ if (!rc)
+ break;
+
+ readed = read(fd, &buf, buf_size - 1);
+ for (i = 0; i < readed; i++) {
+ if (line_used + 1 >= line_size) {
+ line = realloc(line, line_size * 2);
+ line_size *= 2;
+ igt_assert(line);
+ }
+ line[line_used++] = buf[i];
+ if (buf[i] == '\n') {
+ line[line_used] = '\0';
+ kmsg_error_line_parse(line, error_msg);
+ line_used = 0;
+ }
+ }
+ }
+ free(line);
+}
diff --git a/lib/drmtest.h b/lib/drmtest.h
index a9fd0bc..05e3629 100644
--- a/lib/drmtest.h
+++ b/lib/drmtest.h
@@ -413,4 +413,17 @@ void igt_enable_prefault(void);
/* suspend and auto-resume system */
void igt_system_suspend_autoresume(void);
+/* Returns the fd for the other functions. */
+int kmsg_error_setup(void);
+/* Closes the fd */
+void kmsg_error_teardown(int fd);
+/* Skip to the end of the kmsg fd, so that the next time you call
+ * kmsg_error_detect() you will only parse the new messages. */
+void kmsg_error_reset(int fd);
+/* Reads all the new Kernel messages since the last time you called
+ * kmsg_error_teardown, and also waits for new messages for timeout_ms. In case
+ * we find any error we'll also print error_msg. Uses igt_assert, so no need to
+ * check for return values. */
+void kmsg_error_detect(int fd, int timeout_ms, const char *error_msg);
+
#endif /* DRMTEST_H */
--
1.8.3.1
More information about the Intel-gfx
mailing list