@@ -3410,7 +3410,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
34103410 * @syslog: include the "<4>" prefixes
34113411 * @buf: buffer to copy the line to
34123412 * @size: maximum size of the buffer
3413- * @len : length of line placed into buffer
3413+ * @len_out : length of line placed into buffer
34143414 *
34153415 * Start at the end of the kmsg buffer and fill the provided buffer
34163416 * with as many of the *youngest* kmsg records that fit into it.
@@ -3424,20 +3424,18 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
34243424 * read.
34253425 */
34263426bool kmsg_dump_get_buffer (struct kmsg_dumper * dumper , bool syslog ,
3427- char * buf , size_t size , size_t * len )
3427+ char * buf , size_t size , size_t * len_out )
34283428{
34293429 struct printk_info info ;
34303430 unsigned int line_count ;
34313431 struct printk_record r ;
34323432 unsigned long flags ;
34333433 u64 seq ;
34343434 u64 next_seq ;
3435- size_t l = 0 ;
3435+ size_t len = 0 ;
34363436 bool ret = false;
34373437 bool time = printk_time ;
34383438
3439- prb_rec_init_rd (& r , & info , buf , size );
3440-
34413439 if (!dumper -> active || !buf || !size )
34423440 goto out ;
34433441
@@ -3455,48 +3453,54 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
34553453 goto out ;
34563454 }
34573455
3458- /* calculate length of entire buffer */
3459- seq = dumper -> cur_seq ;
3460- while (prb_read_valid_info (prb , seq , & info , & line_count )) {
3461- if (r .info -> seq >= dumper -> next_seq )
3456+ /*
3457+ * Find first record that fits, including all following records,
3458+ * into the user-provided buffer for this dump.
3459+ */
3460+
3461+ prb_for_each_info (dumper -> cur_seq , prb , seq , & info , & line_count ) {
3462+ if (info .seq >= dumper -> next_seq )
34623463 break ;
3463- l += get_record_print_text_size (& info , line_count , syslog , time );
3464- seq = r .info -> seq + 1 ;
3464+ len += get_record_print_text_size (& info , line_count , syslog , time );
34653465 }
34663466
3467- /* move first record forward until length fits into the buffer */
3468- seq = dumper -> cur_seq ;
3469- while (l >= size && prb_read_valid_info (prb , seq ,
3470- & info , & line_count )) {
3471- if (r .info -> seq >= dumper -> next_seq )
3467+ /*
3468+ * Move first record forward until length fits into the buffer. Ignore
3469+ * newest messages that were not counted in the above cycle. Messages
3470+ * might appear and get lost in the meantime. This is the best effort
3471+ * that prevents an infinite loop.
3472+ */
3473+ prb_for_each_info (dumper -> cur_seq , prb , seq , & info , & line_count ) {
3474+ if (len < size || info .seq >= dumper -> next_seq )
34723475 break ;
3473- l -= get_record_print_text_size (& info , line_count , syslog , time );
3474- seq = r .info -> seq + 1 ;
3476+ len -= get_record_print_text_size (& info , line_count , syslog , time );
34753477 }
34763478
3477- /* last message in next interation */
3479+ /*
3480+ * Next kmsg_dump_get_buffer() invocation will dump block of
3481+ * older records stored right before this one.
3482+ */
34783483 next_seq = seq ;
34793484
3480- /* actually read text into the buffer now */
3481- l = 0 ;
3482- while (prb_read_valid (prb , seq , & r )) {
3485+ prb_rec_init_rd (& r , & info , buf , size );
3486+
3487+ len = 0 ;
3488+ prb_for_each_record (seq , prb , seq , & r ) {
34833489 if (r .info -> seq >= dumper -> next_seq )
34843490 break ;
34853491
3486- l += record_print_text (& r , syslog , time );
3492+ len += record_print_text (& r , syslog , time );
34873493
3488- /* adjust record to store to remaining buffer space */
3489- prb_rec_init_rd (& r , & info , buf + l , size - l );
3490-
3491- seq = r .info -> seq + 1 ;
3494+ /* Adjust record to store to remaining buffer space. */
3495+ prb_rec_init_rd (& r , & info , buf + len , size - len );
34923496 }
34933497
34943498 dumper -> next_seq = next_seq ;
34953499 ret = true;
34963500 logbuf_unlock_irqrestore (flags );
34973501out :
3498- if (len )
3499- * len = l ;
3502+ if (len_out )
3503+ * len_out = len ;
35003504 return ret ;
35013505}
35023506EXPORT_SYMBOL_GPL (kmsg_dump_get_buffer );
0 commit comments