[PATCH 1/2] drmtest: introduce kmsg_error functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx>

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@xxxxxxxxx>
---
 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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux