From: Petr Mladek <pmladek@suse.com>
To: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Andreas Schwab <schwab@linux-m68k.org>,
linux-m68k@vger.kernel.org,
John Ogness <john.ogness@linutronix.de>,
"open list:SERIAL DRIVERS" <linux-serial@vger.kernel.org>
Subject: Re: [PATCH] m68k: nfcon: don't call console_is_registered in nfcon_device
Date: Thu, 20 Aug 2026 14:57:04 +0200 [thread overview]
Message-ID: <aob5oO_7qxII_qTB@pathway.suse.cz> (raw)
In-Reply-To: <CAMuHMdU4C+W6Tpsn3Vr_kqmuU2Vzg7ExXhspmB5qNWMZ3Wnfeg@mail.gmail.com>
On Mon 2026-08-17 11:26:57, Geert Uytterhoeven wrote:
> Hi Andreas,
>
> CC john, petr, serial
>
> Thanks for your patch!
>
> On Sat, 15 Aug 2026 at 09:33, Andreas Schwab <schwab@linux-m68k.org> wrote:
> > Since 7c2af0f634f1 ("tty: tty_io: use console_list_lock for list
> > synchronization") show_cons_active calls the device method under the
> > console_list_lock, but console_is_registered tries to acquire
> > console_list_lock as well, causing a deadlock. It should not be necessary
> > to check console_is_registered here since the function should not be
> > called in the fist place when the console is not registered.
>
> Nice catch!
+1
> > Fixes: 7c2af0f634f1 ("tty: tty_io: use console_list_lock for list synchronization")
> > Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
>
> Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
> i.e. will queue in the m68k tree for v7.3.
>
> > --- a/arch/m68k/emu/nfcon.c
> > +++ b/arch/m68k/emu/nfcon.c
> > @@ -49,7 +49,7 @@ static void nfcon_write(struct console *con, const char *str,
> > static struct tty_driver *nfcon_device(struct console *con, int *index)
> > {
> > *index = 0;
> > - return console_is_registered(con) ? nfcon_tty_driver : NULL;
>
> Interestingly, that call to console_is_registered() was added in
> commit de61a1a3a0830710 ("tty: nfcon: use console_is_registered()"),
> i.e. in the same series that added the extra locking...
Sigh, we clearly did not check the callers of this function properly
at that time :/
> > + return nfcon_tty_driver;
Honestly, I do not feel comfortable with removing the check
completely.
The commit de61a1a3a083071 ("tty: nfcon: use console_is_registered()"
used console_is_registered() instead of (con->flags & CON_ENABLED).
And CON_ENABLED is historically cleared when the console is suspended,
see console_suspend().
Is is OK to return a valid struct tty_driver for a non-registered
or suspended console for all con->device() callers?
I have found only 4 callers:
$> git grep "\->device("
drivers/tty/serial/kgdboc.c: if (cons->device && cons->device(cons, &idx) == p &&
drivers/tty/tty_io.c: struct tty_driver *drv = cs[i]->device(cs[i], &index);
fs/proc/consoles.c: driver = con->device(con, &index);
kernel/printk/printk.c: driver = c->device(c, index);
These are:
+ configure_kgdboc() in drivers/tty/serial/kgdboc.c
+ show_cons_active() in drivers/tty/tty_io.c
+ show_console_dev() in fs/proc/consoles.c
+ console_device() in kernel/printk/printk.c
, where
+ configure_kgdboc() is used during the system initialization
when the console should not be suspended
+ show_cons_active() and show_console_dev() are questionable.
Maybe, we should not advertise the device to the userspace
when it is suspended.
+ console_device() is used in tty_kopen() -> tty_lookup_driver().
Also here we likely should not allow to open a suspended device.
Let's take a step back:
We should define the locking context for con->device() callback.
It seems that it is called under console_lock() and
console_srcu_read_lock() in:
+ configure_kgdboc()
+ console_device()
and under console_list_lock() and console_lock() in
+ show_console_dev()
+ show_cons_active()
I would put aside the console_lock(). We are trying to obsolete it.
So it is down to
console_srcu_read_lock() vs console_list_lock()
Both of them look reasonable. So, I think about adding a variant
of console_is_registered_srcu_read_locked() which would work
with both locking. Something like:
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
index d41260672e24..d211b6c4da26 100644
--- a/arch/m68k/emu/nfcon.c
+++ b/arch/m68k/emu/nfcon.c
@@ -49,7 +49,7 @@ static void nfcon_write(struct console *con, const char *str,
static struct tty_driver *nfcon_device(struct console *con, int *index)
{
*index = 0;
- return console_is_registered(con) ? nfcon_tty_driver : NULL;
+ return console_is_registered_srcu_read_locked(con) ? nfcon_tty_driver : NULL;
}
static struct console nf_console = {
diff --git a/include/linux/console.h b/include/linux/console.h
index d624200cfc17..b90527db4eca 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -311,7 +311,7 @@ struct nbcon_write_context {
* @name: The name of the console driver
* @write: Legacy write callback to output messages (Optional)
* @read: Read callback for console input (Optional)
- * @device: The underlying TTY device driver (Optional)
+ * @device: The underlying TTY device driver (Optional) [1]
* @unblank: Callback to unblank the console (Optional)
* @setup: Callback for initializing the console (Optional)
* @exit: Callback for teardown of the console (Optional)
@@ -334,6 +334,9 @@ struct nbcon_write_context {
* @kthread: Printer kthread for this console
* @rcuwait: RCU-safe wait object for @kthread waking
* @irq_work: Defer @kthread waking to IRQ work context
+ *
+ * [1] The @device callback must be called under either console_list_lock()
+ * or console_srcu_read_lock().
*/
struct console {
char name[16];
@@ -473,8 +476,13 @@ struct console {
};
#ifdef CONFIG_LOCKDEP
+extern bool console_list_lock_is_held(void);
extern void lockdep_assert_console_list_lock_held(void);
#else
+static inline bool console_list_lock_is_held(void)
+{
+ return 1;
+}
static inline void lockdep_assert_console_list_lock_held(void)
{
}
@@ -555,6 +563,16 @@ static inline bool console_is_registered_locked(const struct console *con)
return !hlist_unhashed(&con->node);
}
+/*
+ * Variant of console_is_registered() when either the console_srcu_read_lock
+ * or console_list_lock is held.
+*/
+static inline bool console_is_registered_srcu_read_locked(const struct console *con)
+{
+ lockdep_assert(console_srcu_read_lock_is_held() || console_list_lock_is_held());
+ return !hlist_unhashed(&con->node);
+}
+
/*
* console_is_registered - Check if the console is registered
* @con: struct console pointer of console to check
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 2fe9a963c823..9b632b91f096 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -109,6 +109,12 @@ static struct lockdep_map console_lock_dep_map = {
.name = "console_lock"
};
+bool console_list_lock_is_held(void)
+{
+ return lockdep_is_held(&console_mutex);
+}
+EXPORT_SYMBOL(console_list_lock_is_held);
+
void lockdep_assert_console_list_lock_held(void)
{
lockdep_assert_held(&console_mutex);
Alternative solution would be to require the srcu locking.
IMHO, it should be perfectly fine to use the srcu_read_lock in
both show_console_dev() and show_cons_active().
What do you think, please?
John?
Best Regards,
Petr
next prev parent reply other threads:[~2026-08-20 12:57 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <87ecfzsv6h.fsf@igel.home>
2026-08-17 9:26 ` [PATCH] m68k: nfcon: don't call console_is_registered in nfcon_device Geert Uytterhoeven
2026-08-20 10:16 ` John Ogness
2026-08-20 12:57 ` Petr Mladek [this message]
2026-08-20 13:38 ` John Ogness
2026-08-20 15:57 ` 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=aob5oO_7qxII_qTB@pathway.suse.cz \
--to=pmladek@suse.com \
--cc=geert@linux-m68k.org \
--cc=john.ogness@linutronix.de \
--cc=linux-m68k@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=schwab@linux-m68k.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox