Messages in this thread Patch in this message | | | From | John Ogness <> | Subject | [PATCH printk-rework 02/12] printk: refactor kmsg_dump_get_buffer() | Date | Tue, 26 Jan 2021 22:21:41 +0106 |
| |
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 <john.ogness@linutronix.de> --- include/linux/kmsg_dump.h | 2 +- kernel/printk/printk.c | 57 ++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 29 deletions(-)
diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index da98846098b5..76cc4122d08e 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 c55cd1820689..1929aa372e7f 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3407,7 +3407,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; @@ -3415,12 +3415,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; @@ -3436,48 +3434,51 @@ 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 */ + /* Keep track of the last message for the next iteration. */ 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.20.1
| |