Commit 4cfc7258 authored by John Ogness's avatar John Ogness Committed by Petr Mladek

printk: ringbuffer: add finalization/extension support

Add support for extending the newest data block. For this, introduce
a new finalization state (desc_finalized) denoting a committed
descriptor that cannot be extended.

Until a record is finalized, a writer can reopen that record to
append new data. Reopening a record means transitioning from the
desc_committed state back to the desc_reserved state.

A writer can explicitly finalize a record if there is no intention
of extending it. Also, records are automatically finalized when a
new record is reserved. This relieves writers of needing to
explicitly finalize while also making such records available to
readers sooner. (Readers can only traverse finalized records.)

Four new memory barrier pairs are introduced. Two of them are
insignificant additions (data_realloc:A/desc_read:D and
data_realloc:A/data_push_tail:B) because they are alternate path
memory barriers that exactly match the purpose, pairing, and
context of the two existing memory barrier pairs they provide an
alternate path for. The other two new memory barrier pairs are
significant additions:

desc_reopen_last:A / _prb_commit:B - When reopening a descriptor,
    ensure the state transitions back to desc_reserved before
    fully trusting the descriptor data.

_prb_commit:B / desc_reserve:D - When committing a descriptor,
    ensure the state transitions to desc_committed before checking
    the head ID to see if the descriptor needs to be finalized.
Signed-off-by: default avatarJohn Ogness <john.ogness@linutronix.de>
Reviewed-by: default avatarPetr Mladek <pmladek@suse.com>
Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20200914123354.832-6-john.ogness@linutronix.de
parent 10dcb06d
...@@ -297,6 +297,7 @@ end ...@@ -297,6 +297,7 @@ end
define dmesg define dmesg
# definitions from kernel/printk/printk_ringbuffer.h # definitions from kernel/printk/printk_ringbuffer.h
set var $desc_committed = 1 set var $desc_committed = 1
set var $desc_finalized = 2
set var $desc_sv_bits = sizeof(long) * 8 set var $desc_sv_bits = sizeof(long) * 8
set var $desc_flags_shift = $desc_sv_bits - 2 set var $desc_flags_shift = $desc_sv_bits - 2
set var $desc_flags_mask = 3 << $desc_flags_shift set var $desc_flags_mask = 3 << $desc_flags_shift
...@@ -313,7 +314,7 @@ define dmesg ...@@ -313,7 +314,7 @@ define dmesg
# skip non-committed record # skip non-committed record
set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift) set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
if ($state == $desc_committed) if ($state == $desc_committed || $state == $desc_finalized)
dump_record $desc $prev_flags dump_record $desc $prev_flags
set var $prev_flags = $desc->info.flags set var $prev_flags = $desc->info.flags
end end
......
This diff is collapsed.
...@@ -116,7 +116,8 @@ struct prb_reserved_entry { ...@@ -116,7 +116,8 @@ struct prb_reserved_entry {
enum desc_state { enum desc_state {
desc_miss = -1, /* ID mismatch (pseudo state) */ desc_miss = -1, /* ID mismatch (pseudo state) */
desc_reserved = 0x0, /* reserved, in use by writer */ desc_reserved = 0x0, /* reserved, in use by writer */
desc_committed = 0x1, /* committed by writer */ desc_committed = 0x1, /* committed by writer, could get reopened */
desc_finalized = 0x2, /* committed, no further modification allowed */
desc_reusable = 0x3, /* free, not yet used by any writer */ desc_reusable = 0x3, /* free, not yet used by any writer */
}; };
...@@ -327,7 +328,10 @@ static inline void prb_rec_init_wr(struct printk_record *r, ...@@ -327,7 +328,10 @@ static inline void prb_rec_init_wr(struct printk_record *r,
bool prb_reserve(struct prb_reserved_entry *e, struct printk_ringbuffer *rb, bool prb_reserve(struct prb_reserved_entry *e, struct printk_ringbuffer *rb,
struct printk_record *r); struct printk_record *r);
bool prb_reserve_in_last(struct prb_reserved_entry *e, struct printk_ringbuffer *rb,
struct printk_record *r, u32 caller_id);
void prb_commit(struct prb_reserved_entry *e); void prb_commit(struct prb_reserved_entry *e);
void prb_final_commit(struct prb_reserved_entry *e);
void prb_init(struct printk_ringbuffer *rb, void prb_init(struct printk_ringbuffer *rb,
char *text_buf, unsigned int text_buf_size, char *text_buf, unsigned int text_buf_size,
......
...@@ -79,6 +79,7 @@ class LxDmesg(gdb.Command): ...@@ -79,6 +79,7 @@ class LxDmesg(gdb.Command):
# definitions from kernel/printk/printk_ringbuffer.h # definitions from kernel/printk/printk_ringbuffer.h
desc_committed = 1 desc_committed = 1
desc_finalized = 2
desc_sv_bits = utils.get_long_type().sizeof * 8 desc_sv_bits = utils.get_long_type().sizeof * 8
desc_flags_shift = desc_sv_bits - 2 desc_flags_shift = desc_sv_bits - 2
desc_flags_mask = 3 << desc_flags_shift desc_flags_mask = 3 << desc_flags_shift
...@@ -98,7 +99,7 @@ class LxDmesg(gdb.Command): ...@@ -98,7 +99,7 @@ class LxDmesg(gdb.Command):
# skip non-committed record # skip non-committed record
state = 3 & (utils.read_u64(descs, desc_off + sv_off + state = 3 & (utils.read_u64(descs, desc_off + sv_off +
counter_off) >> desc_flags_shift) counter_off) >> desc_flags_shift)
if state != desc_committed: if state != desc_committed and state != desc_finalized:
if did == head_id: if did == head_id:
break break
did = (did + 1) & desc_id_mask did = (did + 1) & desc_id_mask
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment