[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251020-printk_legacy_thread_console_lock-v3-2-00f1f0ac055a@thegoodpenguin.co.uk>
Date: Mon, 20 Oct 2025 16:38:06 +0100
From: Andrew Murray <amurray@...goodpenguin.co.uk>
To: Petr Mladek <pmladek@...e.com>, Steven Rostedt <rostedt@...dmis.org>,
John Ogness <john.ogness@...utronix.de>,
Sergey Senozhatsky <senozhatsky@...omium.org>
Cc: linux-kernel@...r.kernel.org,
Andrew Murray <amurray@...goodpenguin.co.uk>
Subject: [PATCH v3 2/3] printk: console_flush_one_record() code cleanup
From: Petr Mladek <pmladek@...e.com>
console_flush_one_record() and console_flush_all() duplicate several
checks. They both want to tell the caller that consoles are not
longer usable in this context because it has lost the lock or
the lock has to be reserved for the panic CPU.
Remove the duplication by changing the semantic of the function
console_flush_one_record() return value and parameters.
The function will return true when it is able to do the job. It means
that there is at least one usable console. And the flushing was
not interrupted by a takeover or panic_on_other_cpu().
Also replace the @any_usable parameter with @try_again. The @try_again
parameter will be set to true when the function could do the job
and at least one console made a progress.
Motivation:
The callers need to know when
+ they should continue flushing => @try_again
+ when the console is flushed => can_do_the_job(return) && !@..._again
+ when @next_seq is valid => same as flushed
+ when lost console_lock => @takeover
The proposed change makes it clear when the function can do
the job. It simplifies the answer for the other questions.
Also the return value from console_flush_one_record() can
be used as return value from console_flush_all().
Reviewed-by: John Ogness <john.ogness@...utronix.de>
Signed-off-by: Petr Mladek <pmladek@...e.com>
---
kernel/printk/printk.c | 59 ++++++++++++++++++++++++++------------------------
1 file changed, 31 insertions(+), 28 deletions(-)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 1c048c66d09919967e57326e1732bd17c10f3c76..6c846d2d37d9d20bad58c6e3a7caada3be9552ca 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -3142,31 +3142,33 @@ static inline void printk_kthreads_check_locked(void) { }
* context.
*
* @next_seq is set to the sequence number after the last available record.
- * The value is valid only when there is at least one usable console and all
- * usable consoles were flushed.
+ * The value is valid only when all usable consoles were flushed. It is
+ * when the function returns true (can do the job) and @try_again parameter
+ * is set to false, see below.
*
* @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.
*
- * @any_usable will be set to true if there are any usable consoles.
+ * @try_again will be set to true when it still makes sense to call this
+ * function again. The function could do the job, see the return value.
+ * And some consoles still make progress.
*
- * Returns true when there was at least one usable console and a record was
- * flushed. A returned false indicates there were no records to flush for any
- * of the consoles. It may also indicate that there were no usable consoles,
- * the context has been lost or there is a panic suitation. Regardless the
- * reason, the caller should assume it is not useful to immediately try again.
+ * Returns true when the function could do the job. Some consoles are usable,
+ * and there was no takeover and no panic_on_other_cpu().
*
* Requires the console_lock.
*/
static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *handover,
- bool *any_usable)
+ bool *try_again)
{
struct console_flush_type ft;
- bool any_progress = false;
+ int any_usable = false;
struct console *con;
int cookie;
+ *try_again = false;
+
printk_get_console_flush_type(&ft);
cookie = console_srcu_read_lock();
@@ -3185,7 +3187,7 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *
if (!console_is_usable(con, flags, !do_cond_resched))
continue;
- *any_usable = true;
+ any_usable = true;
if (flags & CON_NBCON) {
progress = nbcon_legacy_emit_next_record(con, handover, cookie,
@@ -3201,7 +3203,7 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *
* is already released.
*/
if (*handover)
- return false;
+ goto fail;
/* Track the next of the highest seq flushed. */
if (printk_seq > *next_seq)
@@ -3209,21 +3211,28 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *
if (!progress)
continue;
- any_progress = true;
+
+ /*
+ * An usable console made a progress. There might still be
+ * pending messages.
+ */
+ *try_again = true;
/* Allow panic_cpu to take over the consoles safely. */
if (panic_on_other_cpu())
- goto abandon;
+ goto fail_srcu;
if (do_cond_resched)
cond_resched();
}
console_srcu_read_unlock(cookie);
- return any_progress;
+ return any_usable;
-abandon:
+fail_srcu:
console_srcu_read_unlock(cookie);
+fail:
+ *try_again = false;
return false;
}
@@ -3252,24 +3261,18 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *
*/
static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handover)
{
- bool any_usable = false;
- bool any_progress;
+ bool try_again;
+ bool ret;
*next_seq = 0;
*handover = false;
do {
- any_progress = console_flush_one_record(do_cond_resched, next_seq, handover,
- &any_usable);
+ ret = console_flush_one_record(do_cond_resched, next_seq,
+ handover, &try_again);
+ } while (try_again);
- if (*handover)
- return false;
-
- if (panic_on_other_cpu())
- return false;
- } while (any_progress);
-
- return any_usable;
+ return ret;
}
static void __console_flush_and_unlock(void)
--
2.34.1
Powered by blists - more mailing lists