All of lore.kernel.org
 help / color / mirror / Atom feed
From: Petr Mladek <pmladek@suse.com>
To: John Ogness <john.ogness@linutronix.de>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-kernel@vger.kernel.org,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"Paul E. McKenney" <paulmck@kernel.org>
Subject: Re: [PATCH printk v2 33/38] printk: introduce console_list_lock
Date: Thu, 27 Oct 2022 12:09:32 +0200	[thread overview]
Message-ID: <Y1pY3I1ufABvroYj@alley> (raw)
In-Reply-To: <20221019145600.1282823-34-john.ogness@linutronix.de>

Adding Paul into Cc so that he is aware of using a custom SRCU lockdep
check in console_list_lock().

On Wed 2022-10-19 17:01:55, John Ogness wrote:
> Currently there exist races in console_register(), where the types
> of registered consoles are checked (without holding the console_lock)
> and then after acquiring the console_lock, it is assumed that the list
> has not changed. Also, some code that performs console_unregister()
> make similar assumptions.

This sounds like that the list lock is added just to fix the races.
People might wonder why it is not done using console_lock().
My understanding is that removing this responsibility from console_lock() is
the main motivation. It would deserve a comment, e.g.

<proposal>
A solution would be to synchronize this using console_lock(). But it
would require a complex analyze of all console drivers to make sure
that console_lock() is not taken in match() and setup() callbacks.
And splitting the responsibilities of console_lock() is actually
one big motivation here.

Instead, introduce a console_list_lock...
</proposal>

> Introduce a console_list_lock to provide full synchronization for any
> console list changes.

> The console_list_lock also provides synchronization for updates
> to console->flags.

This would deserve some explanation. The synchronization of the list
manipulation is obvious, especially when the lock is called
console_list_lock. But the motivation to use this lock
for console->flags is much more complicated.

I had some problems to create a reasonable mental model about it.
I did split the flags into groups:

  1. Flags that are driver-specific and static. They do not need
     any synchronization:

       + CON_BOOT
       + CON_ANYTIME


  2. Flags that are modified only during console registration [*]:

       + CON_PRINTBUFFER
       + CON_CONSDEV
       + CON_BRL
       + CON_EXTENDED

  3. Flags that might be modified by more operations, namely: console
     registration, start, and stop [*].

       + CON_ENABLED

[*] It is actually more complicated. Some flags are modified also
    outside console registration code. But we are not going to
    synchronize these changes because they are not visible
    to others via console_drivers list.

This explained why it made sense to synchronize console->flags using
console_list_lock. Also this explained why
console_start()/console_stop() were updated in this patch.

The following description would have helped me:

<proposal>
In addition, use console_list_lock also for synchronization of
console->flags updates. All flags are either static or modified
only during the console registration. There are only few
exceptions.

The only exception is CON_ENABLED that is modified also by
console_start()/console_stop(). We need to take console_list_lock()
here as well.

Another exception is when the flags are modified by the console
driver init code before the console gets registered. These will
be ignored because they are not visible to the rest of the system
via console_drivers list.
</proposal>

> Note that one of the various responsibilities of the console_lock is
> also intended to provide this synchronization. Later changes will
> update call sites relying on the console_lock for this purpose. Once
> all call sites have been updated, the console_lock will be relieved
> of synchronizing console_list and console->flags updates.

It seems that this patch actually updates all writers. It would be
nice to mention it to define the scope of this patch.

<proposal>
Note that one of the various responsibilities of the console_lock is
also intended to provide this synchronization. Only the callers that
modify the list or flags are updated here. Later changes will
update the readers Once all call sites have been updated,
the console_lock will be relieved of synchronizing console_list
and console->flags updates.
</proposal>

> diff --git a/include/linux/console.h b/include/linux/console.h
> index 60195cd086dc..bf1e8136424a 100644
> --- a/include/linux/console.h
> +++ b/include/linux/console.h
> @@ -159,8 +159,12 @@ struct console {
>  };
>  
>  #ifdef CONFIG_LOCKDEP
> +extern void lockdep_assert_console_list_lock_held(void);
>  extern bool console_srcu_read_lock_is_held(void);
>  #else
> +static inline void lockdep_assert_console_list_lock_held(void)
> +{
> +}
>  static inline bool console_srcu_read_lock_is_held(void)
>  {
>  	return 1;
> @@ -170,6 +174,9 @@ static inline bool console_srcu_read_lock_is_held(void)
>  extern int console_srcu_read_lock(void);
>  extern void console_srcu_read_unlock(int cookie);
>  
> +extern void console_list_lock(void) __acquires(console_mutex);
> +extern void console_list_unlock(void) __releases(console_mutex);
> +
>  extern struct hlist_head console_list;
>  
>  /**
> @@ -206,10 +213,17 @@ static inline bool console_is_enabled(const struct console *con)
>  	hlist_for_each_entry_srcu(con, &console_list, node,		\
>  				  console_srcu_read_lock_is_held())
>  
> -/*
> - * for_each_console() allows you to iterate on each console
> +/**
> + * for_each_console() - Iterator over registered consoles
> + * @con:	struct console pointer used as loop cursor
> + *
> + * The console list and all struct console fields are immutable while
> + * iterating.

s/all struct console fields/console->flags/  ?

> + *
> + * Requires console_list_lock to be held.
>   */
> -#define for_each_console(con) \
> +#define for_each_console(con)						\
> +	lockdep_assert_console_list_lock_held();			\
>  	hlist_for_each_entry(con, &console_list, node)
>  
>  extern int console_set_on_cmdline;
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index 2faa6e3e2fb8..3615ee6d68fd 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -78,6 +78,9 @@ EXPORT_SYMBOL(ignore_console_lock_warning);
>  int oops_in_progress;
>  EXPORT_SYMBOL(oops_in_progress);
>  
> +/* console_mutex protects console_list and console->flags updates. */

  /*
   * console_mutex protects console_list updates and console->flags updates.
   * The flags are synchronized only for consoles that are registered,
   * accessible via the list.
   */

> +static DEFINE_MUTEX(console_mutex);
> +
>  /*
>   * console_sem protects console_list and console->flags updates, and also
>   * provides serialization for access to the entire console driver system.
> @@ -104,6 +107,11 @@ static struct lockdep_map console_lock_dep_map = {
>  	.name = "console_lock"
>  };
>  
> +void lockdep_assert_console_list_lock_held(void)
> +{
> +	lockdep_assert_held(&console_mutex);
> +}
> +
>  bool console_srcu_read_lock_is_held(void)
>  {
>  	return srcu_read_lock_held(&console_srcu);
> @@ -225,6 +233,40 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
>  }
>  #endif /* CONFIG_PRINTK && CONFIG_SYSCTL */
>  
> +/**
> + * console_list_lock - Lock the console list
> + *
> + * For console list or console->flags updates
> + */
> +void console_list_lock(void)
> +{
> +#ifdef CONFIG_DEBUG_LOCK_ALLOC
> +	/*
> +	 * In unregister_console(), synchronize_srcu() is called with the
> +	 * console_list_lock held. Therefore it is not allowed that the
> +	 * console_list_lock is taken with the srcu_lock held.
> +	 *
> +	 * Whether or not this context is in the read-side critical section
> +	 * can only be detected if the appropriate debug options are enabled.
> +	 */
> +	WARN_ON_ONCE(debug_lockdep_rcu_enabled() &&
> +		     srcu_read_lock_held(&console_srcu));
> +#endif
> +	mutex_lock(&console_mutex);
> +}
> +EXPORT_SYMBOL(console_list_lock);
> +
> +/**
> + * console_list_unlock - Unlock the console list
> + *
> + * Counterpart to console_list_lock()
> + */
> +void console_list_unlock(void)
> +{
> +	mutex_unlock(&console_mutex);
> +}
> +EXPORT_SYMBOL(console_list_unlock);
> +
>  /**
>   * console_srcu_read_lock - Register a new reader for the
>   *	SRCU-protected console list
> @@ -3304,13 +3350,15 @@ void register_console(struct console *newcon)
>  
>  		hlist_for_each_entry_safe(con, tmp, &console_list, node) {
>  			if (con->flags & CON_BOOT)
> -				unregister_console(con);
> +				unregister_console_locked(con);
>  		}
>  	}
> +unlock:
> +	console_list_unlock();
>  }
>  EXPORT_SYMBOL(register_console);
>  
> -int unregister_console(struct console *console)

We should make it clear that it must be locked by console_list_lock().
Many people would expect console_lock() ;-) I would add a comment
and assert.

/* Must be called under console_list_lock(). */

> +static int unregister_console_locked(struct console *console)
>  {

	assert_console_list_lock_held();

>  	int res;
>  

With updated comments:

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

Best Regards,
Petr

  parent reply	other threads:[~2022-10-27 10:09 UTC|newest]

Thread overview: 151+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-19 14:55 [PATCH printk v2 00/38] reduce console_lock scope John Ogness
2022-10-19 14:55 ` John Ogness
2022-10-19 14:55 ` John Ogness
2022-10-19 14:55 ` John Ogness
2022-10-19 14:55 ` [PATCH printk v2 01/38] serial: kgdboc: Lock console list in probe function John Ogness
2022-10-19 15:41   ` Greg Kroah-Hartman
2022-10-24  5:22   ` Sergey Senozhatsky
2022-10-25  0:34   ` Doug Anderson
2022-10-19 14:55 ` [PATCH printk v2 02/38] printk: Convert console_drivers list to hlist John Ogness
2022-10-19 15:44   ` Greg Kroah-Hartman
2022-10-19 21:46     ` John Ogness
2022-10-20  7:43       ` Greg Kroah-Hartman
2022-10-20 12:36   ` Petr Mladek
2022-10-24  5:23   ` Sergey Senozhatsky
2022-10-19 14:55 ` [PATCH printk v2 03/38] printk: Prepare for SRCU console list protection John Ogness
2022-10-19 15:16   ` Miguel Ojeda
2022-10-19 17:12   ` Paul E. McKenney
2022-10-21  8:34   ` Petr Mladek
2022-10-31 13:06     ` John Ogness
2022-10-31 14:09       ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 04/38] printk: introduce console_is_enabled() wrapper John Ogness
2022-10-19 16:01   ` Greg Kroah-Hartman
2022-10-21  8:57   ` Petr Mladek
2022-10-21  9:37     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 05/38] printk: use console_is_enabled() John Ogness
2022-10-21  9:25   ` Petr Mladek
2022-10-31 15:39     ` John Ogness
2022-10-19 14:55 ` [PATCH printk v2 06/38] tty: nfcon: " John Ogness
2022-10-21  9:55   ` Petr Mladek
2022-10-31 15:59     ` John Ogness
2022-11-01  8:57       ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 07/38] um: kmsg_dump: " John Ogness
2022-10-19 14:55   ` John Ogness
2022-10-21 12:46   ` Petr Mladek
2022-10-21 12:46     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 08/38] efi: earlycon: " John Ogness
2022-10-19 15:32   ` Ard Biesheuvel
2022-10-21 12:53   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 09/38] netconsole: " John Ogness
2022-10-21 13:14   ` Petr Mladek
2022-11-04 15:12     ` John Ogness
2022-10-19 14:55 ` [PATCH printk v2 10/38] tty: hvc: " John Ogness
2022-10-19 14:55   ` John Ogness
2022-10-19 16:01   ` Greg Kroah-Hartman
2022-10-19 16:01     ` Greg Kroah-Hartman
2022-10-21 13:22   ` Petr Mladek
2022-10-21 13:22     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 11/38] tty: serial: earlycon: " John Ogness
2022-10-19 16:01   ` Greg Kroah-Hartman
2022-10-21 13:51   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 12/38] tty: serial: kgdboc: " John Ogness
2022-10-19 16:00   ` Greg Kroah-Hartman
2022-10-21 14:10   ` Petr Mladek
2022-10-24 22:46   ` Doug Anderson
2022-10-25  0:49     ` Doug Anderson
2022-10-25 11:28       ` John Ogness
2022-11-04 16:23         ` John Ogness
2022-11-07  8:47           ` Petr Mladek
2022-11-07  9:45             ` John Ogness
2022-10-19 14:55 ` [PATCH printk v2 13/38] tty: serial: pic32_uart: " John Ogness
2022-10-19 16:01   ` Greg Kroah-Hartman
2022-10-21 14:11   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 14/38] tty: serial: samsung_tty: " John Ogness
2022-10-19 14:55   ` John Ogness
2022-10-19 16:00   ` Greg Kroah-Hartman
2022-10-19 16:00     ` Greg Kroah-Hartman
2022-10-21 14:14   ` Petr Mladek
2022-10-21 14:14     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 15/38] tty: serial: serial_core: " John Ogness
2022-10-19 16:00   ` Greg Kroah-Hartman
2022-10-21 14:14   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 16/38] tty: serial: xilinx_uartps: " John Ogness
2022-10-19 14:55   ` John Ogness
2022-10-19 16:01   ` Greg Kroah-Hartman
2022-10-19 16:01     ` Greg Kroah-Hartman
2022-10-21 14:23   ` Petr Mladek
2022-10-21 14:23     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 17/38] tty: tty_io: " John Ogness
2022-10-19 16:00   ` Greg Kroah-Hartman
2022-10-21 14:24   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 18/38] usb: early: xhci-dbc: " John Ogness
2022-10-19 16:01   ` Greg Kroah-Hartman
2022-10-21 14:27   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 19/38] kdb: kdb_io: " John Ogness
2022-10-21 14:28   ` Petr Mladek
2022-10-25  0:34   ` Doug Anderson
2022-10-19 14:55 ` [PATCH printk v2 20/38] um: kmsg_dumper: use srcu console list iterator John Ogness
2022-10-19 14:55   ` John Ogness
2022-10-21 14:56   ` Petr Mladek
2022-10-21 14:56     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 21/38] serial: kgdboc: " John Ogness
2022-10-19 16:02   ` Greg Kroah-Hartman
2022-10-21 15:09   ` Petr Mladek
2022-10-25  0:33     ` Doug Anderson
2022-10-19 14:55 ` [PATCH printk v2 22/38] serial: kgdboc: document console_lock usage John Ogness
2022-10-20  7:42   ` Greg Kroah-Hartman
2022-10-25  0:36   ` Doug Anderson
2022-10-25 10:09   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 23/38] tty: tty_io: " John Ogness
2022-10-20  7:43   ` Greg Kroah-Hartman
2022-10-25 13:31   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 24/38] xen: fbfront: use srcu console list iterator John Ogness
2022-10-19 14:55   ` John Ogness
2022-10-25 13:39   ` Petr Mladek
2022-10-25 13:39     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 25/38] proc: consoles: document console_lock usage John Ogness
2022-10-25 14:40   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 26/38] kdb: use srcu console list iterator John Ogness
2022-10-25  0:47   ` Doug Anderson
2022-10-25 14:59     ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 27/38] printk: console_flush_all: " John Ogness
2022-10-25 15:17   ` Petr Mladek
2022-11-07  0:00     ` John Ogness
2022-11-07 13:03       ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 28/38] printk: console_unblank: " John Ogness
2022-10-25 15:28   ` Petr Mladek
2022-10-25 15:31   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 29/38] printk: console_flush_on_panic: " John Ogness
2022-10-25 15:32   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 30/38] printk: console_device: " John Ogness
2022-10-25 15:35   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 31/38] printk: register_console: " John Ogness
2022-10-26  8:20   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 32/38] printk: __pr_flush: " John Ogness
2022-10-26  8:33   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 33/38] printk: introduce console_list_lock John Ogness
2022-10-20  7:53   ` Greg Kroah-Hartman
2022-10-27 10:09   ` Petr Mladek [this message]
2022-10-27 18:50     ` Paul E. McKenney
2022-10-28 18:09       ` Boqun Feng
2022-10-28 18:42         ` Paul E. McKenney
2022-11-07 10:10       ` John Ogness
2022-11-07 16:16         ` Paul E. McKenney
2022-10-19 14:55 ` [PATCH printk v2 34/38] serial: kgdboc: use console_list_lock instead of console_lock John Ogness
2022-10-20  7:52   ` Greg Kroah-Hartman
2022-10-27 10:13   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 35/38] tty: tty_io: use console_list_lock for list synchronization John Ogness
2022-10-20  7:43   ` Greg Kroah-Hartman
2022-10-27 10:17   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 36/38] proc: consoles: use console_list_lock for list iteration John Ogness
2022-10-27 12:02   ` Petr Mladek
2022-10-19 14:55 ` [PATCH printk v2 37/38] printk: relieve console_lock of list synchronization duties John Ogness
2022-10-27 12:40   ` Petr Mladek
2022-10-19 14:56 ` [PATCH printk v2 38/38] printk, xen: fbfront: create/use safe function for forcing preferred John Ogness
2022-10-19 14:56   ` John Ogness
2022-10-27 13:18   ` Petr Mladek
2022-10-27 13:18     ` Petr Mladek
2022-10-27 13:35     ` John Ogness
2022-10-27 13:35       ` John Ogness
2022-10-27 14:27       ` Petr Mladek
2022-10-27 14:27         ` Petr Mladek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y1pY3I1ufABvroYj@alley \
    --to=pmladek@suse.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=john.ogness@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=paulmck@kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=senozhatsky@chromium.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.