[printk,v2,28/38] printk: console_unblank: use srcu console list iterator

Message ID 20221019145600.1282823-29-john.ogness@linutronix.de
State New
Headers
Series reduce console_lock scope |

Commit Message

John Ogness Oct. 19, 2022, 2:55 p.m. UTC
  Use srcu console list iteration for console list traversal.

Document why the console_lock is still necessary.

Signed-off-by: John Ogness <john.ogness@linutronix.de>
---
 kernel/printk/printk.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
  

Comments

Petr Mladek Oct. 25, 2022, 3:28 p.m. UTC | #1
On Wed 2022-10-19 17:01:50, John Ogness wrote:
> Use srcu console list iteration for console list traversal.
> 
> Document why the console_lock is still necessary.
> 
> Signed-off-by: John Ogness <john.ogness@linutronix.de>

Reviewed-by: Petr Mladek <pmladek@suse.com>

See a note below.

> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -2948,10 +2948,14 @@ EXPORT_SYMBOL(console_conditional_schedule);
>  void console_unblank(void)
>  {
>  	struct console *c;
> +	int cookie;
>  
>  	/*
> -	 * console_unblank can no longer be called in interrupt context unless
> -	 * oops_in_progress is set to 1..
> +	 * Stop console printing because the unblank() callback may
> +	 * assume the console is not within its write() callback.

From some reason, I believe this even without more details. I expect
that unbank() would need to refresh the screen and use similar
code as the write() callback.

It is different than the device() callback where the dependency is
less obvious.

Best Regards,
Petr

> +	 *
> +	 * If @oops_in_progress is set, this may be an atomic context.
> +	 * In that case, attempt a trylock as best-effort.
>  	 */
>  	if (oops_in_progress) {
>  		if (down_trylock_console_sem() != 0)
> @@ -2961,9 +2965,14 @@ void console_unblank(void)
>  
>  	console_locked = 1;
>  	console_may_schedule = 0;
> -	for_each_console(c)
> +
> +	cookie = console_srcu_read_lock();
> +	for_each_console_srcu(c) {
>  		if (console_is_enabled(c) && c->unblank)
>  			c->unblank();
> +	}
> +	console_srcu_read_unlock(cookie);
> +
>  	console_unlock();
>  
>  	if (!oops_in_progress)
  
Petr Mladek Oct. 25, 2022, 3:31 p.m. UTC | #2
On Wed 2022-10-19 17:01:50, John Ogness wrote:
> Use srcu console list iteration for console list traversal.
> 
> Document why the console_lock is still necessary.
> 
> Signed-off-by: John Ogness <john.ogness@linutronix.de>

Reviewed-by: Petr Mladek <pmladek@suse.com>

Best Regards,
Petr
  

Patch

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index c4d5d58b5977..0c37ab208395 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2948,10 +2948,14 @@  EXPORT_SYMBOL(console_conditional_schedule);
 void console_unblank(void)
 {
 	struct console *c;
+	int cookie;
 
 	/*
-	 * console_unblank can no longer be called in interrupt context unless
-	 * oops_in_progress is set to 1..
+	 * Stop console printing because the unblank() callback may
+	 * assume the console is not within its write() callback.
+	 *
+	 * If @oops_in_progress is set, this may be an atomic context.
+	 * In that case, attempt a trylock as best-effort.
 	 */
 	if (oops_in_progress) {
 		if (down_trylock_console_sem() != 0)
@@ -2961,9 +2965,14 @@  void console_unblank(void)
 
 	console_locked = 1;
 	console_may_schedule = 0;
-	for_each_console(c)
+
+	cookie = console_srcu_read_lock();
+	for_each_console_srcu(c) {
 		if (console_is_enabled(c) && c->unblank)
 			c->unblank();
+	}
+	console_srcu_read_unlock(cookie);
+
 	console_unlock();
 
 	if (!oops_in_progress)