diff options
author | Petri Latvala <petri.latvala@intel.com> | 2020-03-12 11:59:44 +0200 |
---|---|---|
committer | Petri Latvala <petri.latvala@intel.com> | 2020-03-13 11:38:18 +0200 |
commit | 5cbe047658f1a8009c3ab0f2684883dfe98b5610 (patch) | |
tree | ec6b8d515570cc37cf292434e39f64b6dbc3adfd /runner | |
parent | 4ebe1e296d1121d08a2767a0f511eab64d0a894d (diff) |
runner: Read all kernel logs when there are logs
Instead of reading one record at a time between select() calls and
tainted-checks etc, use the same at-the-end dmesg dumper whenever
there's activity in /dev/kmsg. It's possible that the occasional chunk
of missing dmesg we're sometimes hitting is due to reading too slowly,
especially if there's a huge gem traceback.
Also print a clear message if we hit a log buffer underrun so we know
it.
Reference: https://gitlab.freedesktop.org/drm/igt-gpu-tools/issues/79
Signed-off-by: Petri Latvala <petri.latvala@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'runner')
-rw-r--r-- | runner/executor.c | 66 |
1 files changed, 34 insertions, 32 deletions
diff --git a/runner/executor.c b/runner/executor.c index 790f99db..c4b99115 100644 --- a/runner/executor.c +++ b/runner/executor.c @@ -537,7 +537,7 @@ void close_outputs(int *fds) } } -static void dump_dmesg(int kmsgfd, int outfd) +static int dump_dmesg(int kmsgfd, int outfd) { /* * Write kernel messages to the log file until we reach @@ -546,29 +546,31 @@ static void dump_dmesg(int kmsgfd, int outfd) * message to match against, or stop when we reach EAGAIN. */ - int comparefd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + int comparefd; unsigned flags; unsigned long long seq, cmpseq, usec; char cont; char buf[2048]; ssize_t r; - if (comparefd < 0) - return; - lseek(comparefd, 0, SEEK_END); + if (kmsgfd < 0) + return 0; - if (fcntl(kmsgfd, F_SETFL, O_NONBLOCK)) { - close(comparefd); - return; + comparefd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + if (comparefd < 0) { + errf("Error opening another fd for /dev/kmsg\n"); + return -1; } + lseek(comparefd, 0, SEEK_END); while (1) { if (comparefd >= 0) { r = read(comparefd, buf, sizeof(buf) - 1); if (r < 0) { if (errno != EAGAIN && errno != EPIPE) { + errf("Warning: Error reading kmsg comparison record: %m\n"); close(comparefd); - return; + return 0; } } else { buf[r] = '\0'; @@ -582,16 +584,21 @@ static void dump_dmesg(int kmsgfd, int outfd) } r = read(kmsgfd, buf, sizeof(buf)); - if (r <= 0) { - if (errno == EPIPE) + if (r < 0) { + if (errno == EPIPE) { + errf("Warning: kernel log ringbuffer underflow, some records lost.\n"); + continue; + } else if (errno == EINVAL) { + errf("Warning: Buffer too small for kernel log record, record lost.\n"); continue; + } else if (errno != EAGAIN) { + errf("Error reading from kmsg: %m\n"); + return errno; + } - /* - * If EAGAIN, we're done. If some other error, - * we can't do anything anyway. - */ + /* EAGAIN, so we're done dumping */ close(comparefd); - return; + return 0; } write(outfd, buf, r); @@ -604,7 +611,7 @@ static void dump_dmesg(int kmsgfd, int outfd) * enough. */ if (seq >= cmpseq) - return; + return 0; } } } @@ -939,22 +946,17 @@ static int monitor_output(pid_t child, } if (kmsgfd >= 0 && FD_ISSET(kmsgfd, &set)) { + int dmesgstatus; + time_last_activity = time_now; - s = read(kmsgfd, buf, sizeof(buf)); - if (s < 0) { - if (errno != EPIPE && errno != EINVAL) { - errf("Error reading from kmsg, stopping monitoring: %m\n"); - close(kmsgfd); - kmsgfd = -1; - } else if (errno == EINVAL) { - errf("Warning: Buffer too small for kernel log record, record lost.\n"); - } - } else { - write(outputs[_F_DMESG], buf, s); - if (settings->sync) { - fdatasync(outputs[_F_DMESG]); - } + dmesgstatus = dump_dmesg(kmsgfd, outputs[_F_DMESG]); + if (settings->sync) + fdatasync(outputs[_F_DMESG]); + + if (dmesgstatus) { + close(kmsgfd); + kmsgfd = -1; } } @@ -1256,7 +1258,7 @@ static int execute_next_entry(struct execute_state *state, goto out_pipe; } - if ((kmsgfd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC)) < 0) { + if ((kmsgfd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC | O_NONBLOCK)) < 0) { errf("Warning: Cannot open /dev/kmsg\n"); } else { /* TODO: Checking of abort conditions in pre-execute dmesg */ |