Skip to content

Commit ac7d784

Browse files
jognesspmladek
authored andcommitted
printk: Wait for all reserved records with pr_flush()
Currently pr_flush() will only wait for records that were available to readers at the time of the call (using prb_next_seq()). But there may be more records (non-finalized) that have following finalized records. pr_flush() should wait for these to print as well. Particularly because any trailing finalized records may be the messages that the calling context wants to ensure are printed. Add a new ringbuffer function prb_next_reserve_seq() to return the sequence number following the most recently reserved record. This guarantees that pr_flush() will wait until all current printk() messages (completed or in progress) have been printed. Fixes: 3b604ca ("printk: add pr_flush()") Signed-off-by: John Ogness <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Petr Mladek <[email protected]>
1 parent 584528d commit ac7d784

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

kernel/printk/printk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3755,7 +3755,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
37553755

37563756
might_sleep();
37573757

3758-
seq = prb_next_seq(prb);
3758+
seq = prb_next_reserve_seq(prb);
37593759

37603760
/* Flush the consoles so that records up to @seq are printed. */
37613761
console_lock();

kernel/printk/printk_ringbuffer.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,111 @@ u64 prb_first_seq(struct printk_ringbuffer *rb)
19861986
return seq;
19871987
}
19881988

1989+
/**
1990+
* prb_next_reserve_seq() - Get the sequence number after the most recently
1991+
* reserved record.
1992+
*
1993+
* @rb: The ringbuffer to get the sequence number from.
1994+
*
1995+
* This is the public function available to readers to see what sequence
1996+
* number will be assigned to the next reserved record.
1997+
*
1998+
* Note that depending on the situation, this value can be equal to or
1999+
* higher than the sequence number returned by prb_next_seq().
2000+
*
2001+
* Context: Any context.
2002+
* Return: The sequence number that will be assigned to the next record
2003+
* reserved.
2004+
*/
2005+
u64 prb_next_reserve_seq(struct printk_ringbuffer *rb)
2006+
{
2007+
struct prb_desc_ring *desc_ring = &rb->desc_ring;
2008+
unsigned long last_finalized_id;
2009+
atomic_long_t *state_var;
2010+
u64 last_finalized_seq;
2011+
unsigned long head_id;
2012+
struct prb_desc desc;
2013+
unsigned long diff;
2014+
struct prb_desc *d;
2015+
int err;
2016+
2017+
/*
2018+
* It may not be possible to read a sequence number for @head_id.
2019+
* So the ID of @last_finailzed_seq is used to calculate what the
2020+
* sequence number of @head_id will be.
2021+
*/
2022+
2023+
try_again:
2024+
last_finalized_seq = desc_last_finalized_seq(rb);
2025+
2026+
/*
2027+
* @head_id is loaded after @last_finalized_seq to ensure that
2028+
* it points to the record with @last_finalized_seq or newer.
2029+
*
2030+
* Memory barrier involvement:
2031+
*
2032+
* If desc_last_finalized_seq:A reads from
2033+
* desc_update_last_finalized:A, then
2034+
* prb_next_reserve_seq:A reads from desc_reserve:D.
2035+
*
2036+
* Relies on:
2037+
*
2038+
* RELEASE from desc_reserve:D to desc_update_last_finalized:A
2039+
* matching
2040+
* ACQUIRE from desc_last_finalized_seq:A to prb_next_reserve_seq:A
2041+
*
2042+
* Note: desc_reserve:D and desc_update_last_finalized:A can be
2043+
* different CPUs. However, the desc_update_last_finalized:A CPU
2044+
* (which performs the release) must have previously seen
2045+
* desc_read:C, which implies desc_reserve:D can be seen.
2046+
*/
2047+
head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_next_reserve_seq:A) */
2048+
2049+
d = to_desc(desc_ring, last_finalized_seq);
2050+
state_var = &d->state_var;
2051+
2052+
/* Extract the ID, used to specify the descriptor to read. */
2053+
last_finalized_id = DESC_ID(atomic_long_read(state_var));
2054+
2055+
/* Ensure @last_finalized_id is correct. */
2056+
err = desc_read_finalized_seq(desc_ring, last_finalized_id, last_finalized_seq, &desc);
2057+
2058+
if (err == -EINVAL) {
2059+
if (last_finalized_seq == 0) {
2060+
/*
2061+
* No record has been finalized or even reserved yet.
2062+
*
2063+
* The @head_id is initialized such that the first
2064+
* increment will yield the first record (seq=0).
2065+
* Handle it separately to avoid a negative @diff
2066+
* below.
2067+
*/
2068+
if (head_id == DESC0_ID(desc_ring->count_bits))
2069+
return 0;
2070+
2071+
/*
2072+
* One or more descriptors are already reserved. Use
2073+
* the descriptor ID of the first one (@seq=0) for
2074+
* the @diff below.
2075+
*/
2076+
last_finalized_id = DESC0_ID(desc_ring->count_bits) + 1;
2077+
} else {
2078+
/* Record must have been overwritten. Try again. */
2079+
goto try_again;
2080+
}
2081+
}
2082+
2083+
/* Diff of known descriptor IDs to compute related sequence numbers. */
2084+
diff = head_id - last_finalized_id;
2085+
2086+
/*
2087+
* @head_id points to the most recently reserved record, but this
2088+
* function returns the sequence number that will be assigned to the
2089+
* next (not yet reserved) record. Thus +1 is needed.
2090+
*/
2091+
return (last_finalized_seq + diff + 1);
2092+
}
2093+
19892094
/*
19902095
* Non-blocking read of a record.
19912096
*

kernel/printk/printk_ringbuffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ bool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq,
395395
u64 prb_first_seq(struct printk_ringbuffer *rb);
396396
u64 prb_first_valid_seq(struct printk_ringbuffer *rb);
397397
u64 prb_next_seq(struct printk_ringbuffer *rb);
398+
u64 prb_next_reserve_seq(struct printk_ringbuffer *rb);
398399

399400
#ifdef CONFIG_64BIT
400401

0 commit comments

Comments
 (0)