From d7985b936918448708ec582eae418a02a840db84 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Mon, 30 Nov 2020 01:41:56 +0106 Subject: [PATCH 084/323] printk: refactor kmsg_dump_get_buffer() Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patches-5.10.215-rt107.tar.xz kmsg_dump_get_buffer() requires nearly the same logic as syslog_print_all(), but uses different variable names and does not make use of the ringbuffer loop macros. Modify kmsg_dump_get_buffer() so that the implementation is as similar to syslog_print_all() as possible. A follow-up commit will move this common logic into a separate helper function. Signed-off-by: John Ogness Reviewed-by: Petr Mladek Signed-off-by: Sebastian Andrzej Siewior --- include/linux/kmsg_dump.h | 2 +- kernel/printk/printk.c | 60 +++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index 235c50982c2d7..4095a34db0fa3 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -62,7 +62,7 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, char *line, size_t size, size_t *len); bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, - char *buf, size_t size, size_t *len); + char *buf, size_t size, size_t *len_out); void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 92762417a2b2e..48a3311fabee5 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3458,7 +3458,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_line); * read. */ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, - char *buf, size_t size, size_t *len) + char *buf, size_t size, size_t *len_out) { struct printk_info info; unsigned int line_count; @@ -3466,12 +3466,10 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, unsigned long flags; u64 seq; u64 next_seq; - size_t l = 0; + size_t len = 0; bool ret = false; bool time = printk_time; - prb_rec_init_rd(&r, &info, buf, size); - if (!dumper->active || !buf || !size) goto out; @@ -3489,48 +3487,54 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, goto out; } - /* calculate length of entire buffer */ - seq = dumper->cur_seq; - while (prb_read_valid_info(prb, seq, &info, &line_count)) { - if (r.info->seq >= dumper->next_seq) + /* + * Find first record that fits, including all following records, + * into the user-provided buffer for this dump. + */ + + prb_for_each_info(dumper->cur_seq, prb, seq, &info, &line_count) { + if (info.seq >= dumper->next_seq) break; - l += get_record_print_text_size(&info, line_count, syslog, time); - seq = r.info->seq + 1; + len += get_record_print_text_size(&info, line_count, syslog, time); } - /* move first record forward until length fits into the buffer */ - seq = dumper->cur_seq; - while (l >= size && prb_read_valid_info(prb, seq, - &info, &line_count)) { - if (r.info->seq >= dumper->next_seq) + /* + * Move first record forward until length fits into the buffer. Ignore + * newest messages that were not counted in the above cycle. Messages + * might appear and get lost in the meantime. This is the best effort + * that prevents an infinite loop. + */ + prb_for_each_info(dumper->cur_seq, prb, seq, &info, &line_count) { + if (len < size || info.seq >= dumper->next_seq) break; - l -= get_record_print_text_size(&info, line_count, syslog, time); - seq = r.info->seq + 1; + len -= get_record_print_text_size(&info, line_count, syslog, time); } - /* last message in next interation */ + /* + * Next kmsg_dump_get_buffer() invocation will dump block of + * older records stored right before this one. + */ next_seq = seq; - /* actually read text into the buffer now */ - l = 0; - while (prb_read_valid(prb, seq, &r)) { + prb_rec_init_rd(&r, &info, buf, size); + + len = 0; + prb_for_each_record(seq, prb, seq, &r) { if (r.info->seq >= dumper->next_seq) break; - l += record_print_text(&r, syslog, time); - - /* adjust record to store to remaining buffer space */ - prb_rec_init_rd(&r, &info, buf + l, size - l); + len += record_print_text(&r, syslog, time); - seq = r.info->seq + 1; + /* Adjust record to store to remaining buffer space. */ + prb_rec_init_rd(&r, &info, buf + len, size - len); } dumper->next_seq = next_seq; ret = true; logbuf_unlock_irqrestore(flags); out: - if (len) - *len = l; + if (len_out) + *len_out = len; return ret; } EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer); -- 2.44.0