Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

printk: nbcon: Show replay message on takeover

An emergency or panic context can takeover console ownership
while the current owner was printing a printk message. The
atomic printer will re-print the message that the previous
owner was printing. However, this can look confusing to the
user and may even seem as though a message was lost.

[3430014.1
[3430014.181123] usb 1-2: Product: USB Audio

Add a new field @nbcon_prev_seq to struct console to track
the sequence number to print that was assigned to the previous
console owner. If this matches the sequence number to print
that the current owner is assigned, then a takeover must have
occurred. In this case, print an additional message to inform
the user that the previous message is being printed again.

[3430014.1
** replaying previous printk message **
[3430014.181123] usb 1-2: Product: USB Audio

Signed-off-by: John Ogness <john.ogness@linutronix.de>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20240904120536.115780-12-john.ogness@linutronix.de
Signed-off-by: Petr Mladek <pmladek@suse.com>

authored by

John Ogness and committed by
Petr Mladek
5102981d 75d43037

+40
+2
include/linux/console.h
··· 325 325 * @nbcon_state: State for nbcon consoles 326 326 * @nbcon_seq: Sequence number of the next record for nbcon to print 327 327 * @nbcon_device_ctxt: Context available for non-printing operations 328 + * @nbcon_prev_seq: Seq num the previous nbcon owner was assigned to print 328 329 * @pbufs: Pointer to nbcon private buffer 329 330 * @kthread: Printer kthread for this console 330 331 * @rcuwait: RCU-safe wait object for @kthread waking ··· 460 459 atomic_t __private nbcon_state; 461 460 atomic_long_t __private nbcon_seq; 462 461 struct nbcon_context __private nbcon_device_ctxt; 462 + atomic_long_t __private nbcon_prev_seq; 463 463 464 464 struct printk_buffers *pbufs; 465 465 struct task_struct *kthread;
+1
kernel/printk/internal.h
··· 319 319 320 320 #ifdef CONFIG_PRINTK 321 321 void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped); 322 + void console_prepend_replay(struct printk_message *pmsg); 322 323 #endif
+26
kernel/printk/nbcon.c
··· 946 946 .pbufs = ctxt->pbufs, 947 947 }; 948 948 unsigned long con_dropped; 949 + struct nbcon_state cur; 949 950 unsigned long dropped; 951 + unsigned long ulseq; 950 952 951 953 /* 952 954 * This function should never be called for consoles that have not ··· 988 986 dropped = con_dropped + pmsg.dropped; 989 987 if (dropped && !is_extended) 990 988 console_prepend_dropped(&pmsg, dropped); 989 + 990 + /* 991 + * If the previous owner was assigned the same record, this context 992 + * has taken over ownership and is replaying the record. Prepend a 993 + * message to let the user know the record is replayed. 994 + */ 995 + ulseq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_prev_seq)); 996 + if (__ulseq_to_u64seq(prb, ulseq) == pmsg.seq) { 997 + console_prepend_replay(&pmsg); 998 + } else { 999 + /* 1000 + * Ensure this context is still the owner before trying to 1001 + * update @nbcon_prev_seq. Otherwise the value in @ulseq may 1002 + * not be from the previous owner and instead be some later 1003 + * value from the context that took over ownership. 1004 + */ 1005 + nbcon_state_read(con, &cur); 1006 + if (!nbcon_context_can_proceed(ctxt, &cur)) 1007 + return false; 1008 + 1009 + atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_prev_seq), &ulseq, 1010 + __u64seq_to_ulseq(pmsg.seq)); 1011 + } 991 1012 992 1013 if (!nbcon_context_exit_unsafe(ctxt)) 993 1014 return false; ··· 1671 1646 1672 1647 rcuwait_init(&con->rcuwait); 1673 1648 init_irq_work(&con->irq_work, nbcon_irq_work); 1649 + atomic_long_set(&ACCESS_PRIVATE(con, nbcon_prev_seq), -1UL); 1674 1650 nbcon_state_set(con, &state); 1675 1651 1676 1652 /*
+11
kernel/printk/printk.c
··· 2903 2903 } 2904 2904 2905 2905 /* 2906 + * Prepend the message in @pmsg->pbufs->outbuf with a "replay message". 2907 + * @pmsg->outbuf_len is updated appropriately. 2908 + * 2909 + * @pmsg is the printk message to prepend. 2910 + */ 2911 + void console_prepend_replay(struct printk_message *pmsg) 2912 + { 2913 + console_prepend_message(pmsg, "** replaying previous printk message **\n"); 2914 + } 2915 + 2916 + /* 2906 2917 * Read and format the specified record (or a later record if the specified 2907 2918 * record is not available). 2908 2919 *