Skip to content

Commit 5eb17c1

Browse files
committed
Merge branch 'rework/fast-next-seq' into for-linus
2 parents 1ccd85f + f244b4d commit 5eb17c1

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

kernel/printk/printk_ringbuffer.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,10 @@ static enum desc_state desc_read(struct prb_desc_ring *desc_ring,
474474
* state has been re-checked. A memcpy() for all of @desc
475475
* cannot be used because of the atomic_t @state_var field.
476476
*/
477-
memcpy(&desc_out->text_blk_lpos, &desc->text_blk_lpos,
478-
sizeof(desc_out->text_blk_lpos)); /* LMM(desc_read:C) */
477+
if (desc_out) {
478+
memcpy(&desc_out->text_blk_lpos, &desc->text_blk_lpos,
479+
sizeof(desc_out->text_blk_lpos)); /* LMM(desc_read:C) */
480+
}
479481
if (seq_out)
480482
*seq_out = info->seq; /* also part of desc_read:C */
481483
if (caller_id_out)
@@ -528,7 +530,8 @@ static enum desc_state desc_read(struct prb_desc_ring *desc_ring,
528530
state_val = atomic_long_read(state_var); /* LMM(desc_read:E) */
529531
d_state = get_desc_state(id, state_val);
530532
out:
531-
atomic_long_set(&desc_out->state_var, state_val);
533+
if (desc_out)
534+
atomic_long_set(&desc_out->state_var, state_val);
532535
return d_state;
533536
}
534537

@@ -1449,6 +1452,9 @@ static void desc_make_final(struct prb_desc_ring *desc_ring, unsigned long id)
14491452

14501453
atomic_long_cmpxchg_relaxed(&d->state_var, prev_state_val,
14511454
DESC_SV(id, desc_finalized)); /* LMM(desc_make_final:A) */
1455+
1456+
/* Best effort to remember the last finalized @id. */
1457+
atomic_long_set(&desc_ring->last_finalized_id, id);
14521458
}
14531459

14541460
/**
@@ -1657,7 +1663,12 @@ void prb_commit(struct prb_reserved_entry *e)
16571663
*/
16581664
void prb_final_commit(struct prb_reserved_entry *e)
16591665
{
1666+
struct prb_desc_ring *desc_ring = &e->rb->desc_ring;
1667+
16601668
_prb_commit(e, desc_finalized);
1669+
1670+
/* Best effort to remember the last finalized @id. */
1671+
atomic_long_set(&desc_ring->last_finalized_id, e->id);
16611672
}
16621673

16631674
/*
@@ -2005,9 +2016,39 @@ u64 prb_first_valid_seq(struct printk_ringbuffer *rb)
20052016
*/
20062017
u64 prb_next_seq(struct printk_ringbuffer *rb)
20072018
{
2008-
u64 seq = 0;
2019+
struct prb_desc_ring *desc_ring = &rb->desc_ring;
2020+
enum desc_state d_state;
2021+
unsigned long id;
2022+
u64 seq;
2023+
2024+
/* Check if the cached @id still points to a valid @seq. */
2025+
id = atomic_long_read(&desc_ring->last_finalized_id);
2026+
d_state = desc_read(desc_ring, id, NULL, &seq, NULL);
20092027

2010-
/* Search forward from the oldest descriptor. */
2028+
if (d_state == desc_finalized || d_state == desc_reusable) {
2029+
/*
2030+
* Begin searching after the last finalized record.
2031+
*
2032+
* On 0, the search must begin at 0 because of hack#2
2033+
* of the bootstrapping phase it is not known if a
2034+
* record at index 0 exists.
2035+
*/
2036+
if (seq != 0)
2037+
seq++;
2038+
} else {
2039+
/*
2040+
* The information about the last finalized sequence number
2041+
* has gone. It should happen only when there is a flood of
2042+
* new messages and the ringbuffer is rapidly recycled.
2043+
* Give up and start from the beginning.
2044+
*/
2045+
seq = 0;
2046+
}
2047+
2048+
/*
2049+
* The information about the last finalized @seq might be inaccurate.
2050+
* Search forward to find the current one.
2051+
*/
20112052
while (_prb_read_valid(rb, &seq, NULL, NULL))
20122053
seq++;
20132054

@@ -2044,6 +2085,7 @@ void prb_init(struct printk_ringbuffer *rb,
20442085
rb->desc_ring.infos = infos;
20452086
atomic_long_set(&rb->desc_ring.head_id, DESC0_ID(descbits));
20462087
atomic_long_set(&rb->desc_ring.tail_id, DESC0_ID(descbits));
2088+
atomic_long_set(&rb->desc_ring.last_finalized_id, DESC0_ID(descbits));
20472089

20482090
rb->text_data_ring.size_bits = textbits;
20492091
rb->text_data_ring.data = text_buf;

kernel/printk/printk_ringbuffer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct prb_desc_ring {
7575
struct printk_info *infos;
7676
atomic_long_t head_id;
7777
atomic_long_t tail_id;
78+
atomic_long_t last_finalized_id;
7879
};
7980

8081
/*
@@ -258,6 +259,7 @@ static struct printk_ringbuffer name = { \
258259
.infos = &_##name##_infos[0], \
259260
.head_id = ATOMIC_INIT(DESC0_ID(descbits)), \
260261
.tail_id = ATOMIC_INIT(DESC0_ID(descbits)), \
262+
.last_finalized_id = ATOMIC_INIT(DESC0_ID(descbits)), \
261263
}, \
262264
.text_data_ring = { \
263265
.size_bits = (avgtextbits) + (descbits), \

0 commit comments

Comments
 (0)