From: Petr Mladek <pmladek@suse.com>
To: Andrew Murray <amurray@thegoodpenguin.co.uk>
Cc: Steven Rostedt <rostedt@goodmis.org>,
John Ogness <john.ogness@linutronix.de>,
Sergey Senozhatsky <senozhatsky@chromium.org>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH RFC 2/2] printk: Use console_flush_one_record for legacy printer kthread
Date: Thu, 18 Sep 2025 18:27:26 +0200 [thread overview]
Message-ID: <aMwy7pFM7EExLxaX@pathway.suse.cz> (raw)
In-Reply-To: <20250915-printk_legacy_thread_console_lock-v1-2-f34d42a9bcb3@thegoodpenguin.co.uk>
On Mon 2025-09-15 13:43:06, Andrew Murray wrote:
> The legacy printer kthread uses console_lock and
> __console_flush_and_unlock to flush records to the console. This
> approach results in the console_lock being held for the entire
> duration of a flush. This can result in large waiting times for
> those waiting for console_lock especially where there is a large
> volume of records or where the console is slow (e.g. serial). This
> contention is observed during boot, as the call to filp_open in
> console_on_rootfs will delay progression to userspace until any
> in-flight flush is completed.
It would be great to add here the boot logs from the cover letter
so that the real life numbers are stored in the git log.
> Let's instead use __console_flush_unlocked which releases and
> reacquires console_lock between records.
It seems that the patch does the right thing.
I would just suggest some refactoring, see below.
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -3301,6 +3301,46 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
> return any_usable;
> }
>
> +/*
> + * Print out all remaining records to all consoles.
> + *
> + * @next_seq is set to the sequence number after the last available record.
> + * The value is valid only when this function returns true. It means that all
> + * usable consoles are completely flushed.
> + *
> + * @handover will be set to true if a printk waiter has taken over the
> + * console_lock, in which case the caller is no longer holding the
> + * console_lock. Otherwise it is set to false.
> + *
> + * Returns true when there was at least one usable console and all messages
> + * were flushed to all usable consoles. A returned false informs the caller
> + * that everything was not flushed (either there were no usable consoles or
> + * another context has taken over printing or it is a panic situation and this
> + * is not the panic CPU). Regardless the reason, the caller should assume it
> + * is not useful to immediately try again.
> + */
> +static bool console_flush_all_unlocked(u64 *next_seq, bool *handover)
> +{
> + bool any_usable;
> + bool any_progress;
> +
> + *next_seq = 0;
> + *handover = false;
> +
> + do {
> + console_lock();
> + any_progress = console_flush_one_record(true, next_seq, handover, &any_usable);
> +
> + if (*handover)
> + return false;
> +
> + __console_unlock();
> +
> + } while (any_progress);
> +
> + return any_usable;
> +}
This is yet another console_flush() API with a complicated semantic.
(return value, parameters). It is not bad. But it would be nice
if we did not need it ;-)
> static void __console_flush_and_unlock(void)
> {
> bool do_cond_resched;
> @@ -3346,6 +3386,17 @@ static void __console_flush_and_unlock(void)
> } while (prb_read_valid(prb, next_seq, NULL) && console_trylock());
> }
>
> +static void __console_flush_unlocked(void)
> +{
> + bool handover;
> + bool flushed;
> + u64 next_seq;
> +
> + do {
> + flushed = console_flush_all_unlocked(&next_seq, &handover);
> + } while (flushed && !handover && prb_read_valid(prb, next_seq, NULL));
> +}
The semantic of this function is not much clear from the name.
IMHO, it would be a puzzle for people who would try to understand
the code in the future.
> +
> /**
> * console_unlock - unblock the legacy console subsystem from printing
> *
> @@ -3676,8 +3727,7 @@ static int legacy_kthread_func(void *unused)
> if (kthread_should_stop())
> break;
>
> - console_lock();
> - __console_flush_and_unlock();
> + __console_flush_unlocked();
IMHO, it would be pretty hard to understand what it does by trying to
understand all the layers of the code.
It might be better to open code it. And I would take inspiration
in the nbcon_kthread_func().
I played with the code and came up with:
static int legacy_kthread_func(void *unused)
{
bool any_progress;
wait_for_event:
wait_event_interruptible(legacy_wait, legacy_kthread_should_wakeup());
do {
bool any_usable;
bool handover;
u64 next_seq;
if (kthread_should_stop())
return 0;
console_lock();
any_progress = console_flush_one_record(true, &next_seq, &handover, &any_usable);
if (!handover)
__console_unlock();
/*
* There is no need to check whether there is any usable
* console in this context or whether there are pending
* messages. It is checked by legacy_kthread_should_wakeup()
* anyway. And console_lock() will never succeed again if
* there was panic in progress.
*/
} while (any_progress);
goto wait_for_event;
}
What do you think, please?
Best Regards,
Petr
next prev parent reply other threads:[~2025-09-18 16:27 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-15 12:43 [PATCH RFC 0/2] printk: Release console_lock between printing records in legacy thread Andrew Murray
2025-09-15 12:43 ` [PATCH RFC 1/2] printk: Introduce console_flush_one_record Andrew Murray
2025-09-18 15:22 ` Petr Mladek
2025-09-19 13:06 ` Andrew Murray
2025-09-23 13:30 ` Petr Mladek
2025-09-27 11:10 ` Andrew Murray
2025-09-15 12:43 ` [PATCH RFC 2/2] printk: Use console_flush_one_record for legacy printer kthread Andrew Murray
2025-09-18 16:27 ` Petr Mladek [this message]
2025-09-19 13:38 ` Andrew Murray
2025-09-22 13:27 ` John Ogness
2025-09-23 14:22 ` Petr Mladek
2025-09-27 12:10 ` Andrew Murray
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=aMwy7pFM7EExLxaX@pathway.suse.cz \
--to=pmladek@suse.com \
--cc=amurray@thegoodpenguin.co.uk \
--cc=john.ogness@linutronix.de \
--cc=linux-kernel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=senozhatsky@chromium.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
all inboxes | Powered by JetHome®