[igt-dev] [PATCH i-g-t] lib/kmod: reimplement kmsg_dump()
Petri Latvala
petri.latvala at intel.com
Fri Sep 20 10:25:00 UTC 2019
On Thu, Sep 19, 2019 at 06:07:23PM -0700, Lucas De Marchi wrote:
> /dev/kmsg is record-oriented rather than line-oriented. A short read in
> which the record doesn't fit will return -EINVAL and getline() will stop
> working. This is in general not a problem since the (default) stdio
> buffer is bigger than the maximum record size (4096). However let's
> abide by the kernel ABI rather than relying on the libc buffer size.
>
> While reimplementing, fix the following issues that made me look to the
> implementation in the first place:
>
> 1) we were skipping 1 char in the message, producing messages like the
> one below (see the missing i in intel_pch_type):
> (i915_selftest:3861) igt_kmod-WARNING: ntel_pch_type [i915]] Found Tiger Lake LP PCH
>
> 2) we were printing the key=val pair of kmsg as if it was part of the
> messsages, and even mangling the result looking for a ':':
> (i915_selftest:3861) igt_kmod-WARNING: 000:00:02.0
>
> The ABI for /dev/kmsg stands:
> Accessing the buffer:
> Every read() from the opened device node receives one record
> of the kernel's printk buffer.
>
> [ ... ]
>
> Future extensions might add more comma separated values before
> the terminating ';'. Unknown fields and values should be
> gracefully ignored.
>
> The human readable text string starts directly after the ';'
> and is terminated by a '\n'. Untrusted values derived from
> hardware or other facilities are printed, therefore
> all non-printable characters and '\' itself in the log message
> are escaped by "\x00" C-style hex encoding.
>
> A line starting with ' ', is a continuation line, adding
> key/value pairs to the log message, which provide the machine
> readable context of the message, for reliable processing in
> userspace.
>
> Now the line in (1) print as:
> (i915_selftest:5070) igt_kmod-WARNING: [drm:intel_pch_type [i915]] Found Tiger Lake LP PCH
>
> This also fixes a double close on fclose() already closes the file
> descriptor.
>
> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
> ---
> lib/igt_kmod.c | 43 ++++++++++++++++++++++++++-----------------
> 1 file changed, 26 insertions(+), 17 deletions(-)
>
> diff --git a/lib/igt_kmod.c b/lib/igt_kmod.c
> index 91662eb3..01faca39 100644
> --- a/lib/igt_kmod.c
> +++ b/lib/igt_kmod.c
> @@ -374,25 +374,34 @@ igt_i915_driver_unload(void)
>
> static void kmsg_dump(int fd)
> {
> - FILE *file;
> -
> - file = NULL;
> - if (fd != -1)
> - file = fdopen(fd, "r");
> - if (file) {
> - size_t len = 0;
> - char *line = NULL;
> -
> - while (getline(&line, &len, file) != -1) {
> - char *start = strchr(line, ':');
> - if (start)
> - igt_warn("%s", start + 2);
> - }
> + char record[4096 + 1];
>
> - free(line);
> - fclose(file);
> - } else {
> + if (fd == -1) {
> igt_warn("Unable to retrieve kernel log (from /dev/kmsg)\n");
> + return;
> + }
> +
> + record[sizeof(record) - 1] = '\0';
> +
> + for (;;) {
> + const char *start, *end;
> + ssize_t r;
> +
> + r = read(fd, record, sizeof(record) - 1);
> + if (r < 0) {
> + if (errno == EINTR)
> + continue;
> + if (errno != EAGAIN)
> + igt_warn("kmsg truncated due to unknown error: %m\n");
> + break;
> + }
> +
> + start = strchr(record, ';');
> + if (start) {
> + start++;
> + end = strchrnul(start, '\n');
> + igt_warn("%.*s\n", (int)(end - start), start);
> + }
> }
> }
Reviewed-by: Petri Latvala <petri.latvala at intel.com>
Can I interest you in refactoring this and parse_dmesg_line() in
runner/resultgen.c together? :P
More information about the igt-dev
mailing list