Skip to content

Commit 4260e0e

Browse files
jognesspmladek
authored andcommitted
printk: consolidate kmsg_dump_get_buffer/syslog_print_all code
The logic for finding records to fit into a buffer is the same for kmsg_dump_get_buffer() and syslog_print_all(). Introduce a helper function find_first_fitting_seq() to handle this logic. Signed-off-by: John Ogness <john.ogness@linutronix.de> Reviewed-by: Petr Mladek <pmladek@suse.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Link: https://lore.kernel.org/r/20210303101528.29901-7-john.ogness@linutronix.de
1 parent 726b509 commit 4260e0e

1 file changed

Lines changed: 50 additions & 37 deletions

File tree

kernel/printk/printk.c

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,50 @@ static size_t get_record_print_text_size(struct printk_info *info,
14211421
return ((prefix_len * line_count) + info->text_len + 1);
14221422
}
14231423

1424+
/*
1425+
* Beginning with @start_seq, find the first record where it and all following
1426+
* records up to (but not including) @max_seq fit into @size.
1427+
*
1428+
* @max_seq is simply an upper bound and does not need to exist. If the caller
1429+
* does not require an upper bound, -1 can be used for @max_seq.
1430+
*/
1431+
static u64 find_first_fitting_seq(u64 start_seq, u64 max_seq, size_t size,
1432+
bool syslog, bool time)
1433+
{
1434+
struct printk_info info;
1435+
unsigned int line_count;
1436+
size_t len = 0;
1437+
u64 seq;
1438+
1439+
/* Determine the size of the records up to @max_seq. */
1440+
prb_for_each_info(start_seq, prb, seq, &info, &line_count) {
1441+
if (info.seq >= max_seq)
1442+
break;
1443+
len += get_record_print_text_size(&info, line_count, syslog, time);
1444+
}
1445+
1446+
/*
1447+
* Adjust the upper bound for the next loop to avoid subtracting
1448+
* lengths that were never added.
1449+
*/
1450+
if (seq < max_seq)
1451+
max_seq = seq;
1452+
1453+
/*
1454+
* Move first record forward until length fits into the buffer. Ignore
1455+
* newest messages that were not counted in the above cycle. Messages
1456+
* might appear and get lost in the meantime. This is a best effort
1457+
* that prevents an infinite loop that could occur with a retry.
1458+
*/
1459+
prb_for_each_info(start_seq, prb, seq, &info, &line_count) {
1460+
if (len <= size || info.seq >= max_seq)
1461+
break;
1462+
len -= get_record_print_text_size(&info, line_count, syslog, time);
1463+
}
1464+
1465+
return seq;
1466+
}
1467+
14241468
static int syslog_print(char __user *buf, int size)
14251469
{
14261470
struct printk_info info;
@@ -1492,9 +1536,7 @@ static int syslog_print(char __user *buf, int size)
14921536
static int syslog_print_all(char __user *buf, int size, bool clear)
14931537
{
14941538
struct printk_info info;
1495-
unsigned int line_count;
14961539
struct printk_record r;
1497-
u64 max_seq;
14981540
char *text;
14991541
int len = 0;
15001542
u64 seq;
@@ -1510,21 +1552,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
15101552
* Find first record that fits, including all following records,
15111553
* into the user-provided buffer for this dump.
15121554
*/
1513-
prb_for_each_info(clear_seq, prb, seq, &info, &line_count)
1514-
len += get_record_print_text_size(&info, line_count, true, time);
1515-
1516-
/*
1517-
* Set an upper bound for the next loop to avoid subtracting lengths
1518-
* that were never added.
1519-
*/
1520-
max_seq = seq;
1521-
1522-
/* move first record forward until length fits into the buffer */
1523-
prb_for_each_info(clear_seq, prb, seq, &info, &line_count) {
1524-
if (len <= size || info.seq >= max_seq)
1525-
break;
1526-
len -= get_record_print_text_size(&info, line_count, true, time);
1527-
}
1555+
seq = find_first_fitting_seq(clear_seq, -1, size, true, time);
15281556

15291557
prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX);
15301558

@@ -3427,7 +3455,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
34273455
char *buf, size_t size, size_t *len_out)
34283456
{
34293457
struct printk_info info;
3430-
unsigned int line_count;
34313458
struct printk_record r;
34323459
unsigned long flags;
34333460
u64 seq;
@@ -3455,26 +3482,12 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
34553482

34563483
/*
34573484
* Find first record that fits, including all following records,
3458-
* into the user-provided buffer for this dump.
3485+
* into the user-provided buffer for this dump. Pass in size-1
3486+
* because this function (by way of record_print_text()) will
3487+
* not write more than size-1 bytes of text into @buf.
34593488
*/
3460-
3461-
prb_for_each_info(dumper->cur_seq, prb, seq, &info, &line_count) {
3462-
if (info.seq >= dumper->next_seq)
3463-
break;
3464-
len += get_record_print_text_size(&info, line_count, syslog, time);
3465-
}
3466-
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)
3475-
break;
3476-
len -= get_record_print_text_size(&info, line_count, syslog, time);
3477-
}
3489+
seq = find_first_fitting_seq(dumper->cur_seq, dumper->next_seq,
3490+
size - 1, syslog, time);
34783491

34793492
/*
34803493
* Next kmsg_dump_get_buffer() invocation will dump block of

0 commit comments

Comments
 (0)