printk: console_flush_on_panic: use srcu console list iterator
authorJohn Ogness <john.ogness@linutronix.de>
Wed, 16 Nov 2022 16:21:31 +0000 (17:27 +0106)
committerPetr Mladek <pmladek@suse.com>
Fri, 2 Dec 2022 10:25:01 +0000 (11:25 +0100)
With SRCU it is now safe to traverse the console list, even if
the console_trylock() failed. However, overwriting console->seq
when console_trylock() failed is still an issue.

Switch to SRCU iteration and document remaining issue with
console->seq.

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/20221116162152.193147-20-john.ogness@linutronix.de
kernel/printk/printk.c

index 8e37a35..b789470 100644 (file)
@@ -3050,21 +3050,22 @@ void console_flush_on_panic(enum con_flush_mode mode)
        console_may_schedule = 0;
 
        if (mode == CONSOLE_REPLAY_ALL) {
-               struct hlist_node *tmp;
                struct console *c;
+               int cookie;
                u64 seq;
 
                seq = prb_first_valid_seq(prb);
-               /*
-                * This cannot use for_each_console() because it's not established
-                * that the current context has console locked and neither there is
-                * a guarantee that there is no concurrency in that case.
-                *
-                * Open code it for documentation purposes and pretend that
-                * it works.
-                */
-               hlist_for_each_entry_safe(c, tmp, &console_list, node)
+
+               cookie = console_srcu_read_lock();
+               for_each_console_srcu(c) {
+                       /*
+                        * If the above console_trylock() failed, this is an
+                        * unsynchronized assignment. But in that case, the
+                        * kernel is in "hope and pray" mode anyway.
+                        */
                        c->seq = seq;
+               }
+               console_srcu_read_unlock(cookie);
        }
        console_unlock();
 }