diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2022-01-27 15:41:01 +0100 |
---|---|---|
committer | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2022-01-27 15:41:01 +0100 |
commit | 9383fbe3afce85b624e57990885ae0703c499ad1 (patch) | |
tree | 882664288e000eda4fb763ca4f57330699478304 /patches/0009-printk-add-kthread-console-printers.patch | |
parent | dd833c21fde92e3318e3b43c3a239dc9d0a43a00 (diff) | |
download | linux-rt-9383fbe3afce85b624e57990885ae0703c499ad1.tar.gz |
[ANNOUNCE] v5.17-rc1-rt2v5.17-rc1-rt2-patches
Dear RT folks!
I'm pleased to announce the v5.17-rc1-rt2 patch set.
Changes since v5.17-rc1-rt1:
- Update the printk to the latest version. Patch by John Ogness.
Known issues
- netconsole triggers WARN.
- Valentin Schneider reported a few splats on ARM64, see
https://lkml.kernel.org/r/20210810134127.1394269-1-valentin.schneider@arm.com
The delta patch against v5.17-rc1-rt1 is appended below and can be found here:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.17/incr/patch-5.17-rc1-rt1-rt2.patch.xz
You can get this release via the git tree at:
git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v5.17-rc1-rt2
The RT patch against v5.17-rc1 can be found here:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.17/older/patch-5.17-rc1-rt2.patch.xz
The split quilt queue is available at:
https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.17/older/patches-5.17-rc1-rt2.tar.xz
Sebastian
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Diffstat (limited to 'patches/0009-printk-add-kthread-console-printers.patch')
-rw-r--r-- | patches/0009-printk-add-kthread-console-printers.patch | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/patches/0009-printk-add-kthread-console-printers.patch b/patches/0009-printk-add-kthread-console-printers.patch new file mode 100644 index 000000000000..1fb69d5c3dd4 --- /dev/null +++ b/patches/0009-printk-add-kthread-console-printers.patch @@ -0,0 +1,277 @@ +From: John Ogness <john.ogness@linutronix.de> +Date: Mon, 13 Dec 2021 21:22:17 +0106 +Subject: [PATCH 09/15] printk: add kthread console printers + +Create a kthread for each console to perform console printing. During +normal operation (@system_state == SYSTEM_RUNNING), the kthread +printers are responsible for all printing on their respective +consoles. + +During non-normal operation, console printing is done as it has been: +within the context of the printk caller or within irq work triggered +by the printk caller. + +Console printers synchronize against each other and against console +lockers by taking the console lock for each message that is printed. + +Signed-off-by: John Ogness <john.ogness@linutronix.de> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + include/linux/console.h | 2 + kernel/printk/printk.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 157 insertions(+), 2 deletions(-) + +--- a/include/linux/console.h ++++ b/include/linux/console.h +@@ -153,6 +153,8 @@ struct console { + uint ospeed; + u64 seq; + unsigned long dropped; ++ struct task_struct *thread; ++ + void *data; + struct console *next; + }; +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -348,6 +348,20 @@ static int console_msg_format = MSG_FORM + /* syslog_lock protects syslog_* variables and write access to clear_seq. */ + static DEFINE_MUTEX(syslog_lock); + ++/* ++ * A flag to signify if printk_late_init() has already started the kthread ++ * printers. If true, any later registered consoles must start their own ++ * kthread directly. The flag is write protected by the console_lock. ++ */ ++static bool kthreads_started; ++ ++static inline bool kthread_printers_active(void) ++{ ++ return (kthreads_started && ++ system_state == SYSTEM_RUNNING && ++ !oops_in_progress); ++} ++ + #ifdef CONFIG_PRINTK + DECLARE_WAIT_QUEUE_HEAD(log_wait); + /* All 3 protected by @syslog_lock. */ +@@ -2201,7 +2215,7 @@ asmlinkage int vprintk_emit(int facility + printed_len = vprintk_store(facility, level, dev_info, fmt, args); + + /* If called from the scheduler, we can not call up(). */ +- if (!in_sched) { ++ if (!in_sched && !kthread_printers_active()) { + /* + * Disable preemption to avoid being preempted while holding + * console_sem which would prevent anyone from printing to +@@ -2242,6 +2256,8 @@ asmlinkage __visible int _printk(const c + } + EXPORT_SYMBOL(_printk); + ++static void start_printk_kthread(struct console *con); ++ + #else /* CONFIG_PRINTK */ + + #define CONSOLE_LOG_MAX 0 +@@ -2273,6 +2289,7 @@ static void call_console_driver(struct c + char *dropped_text) {} + static bool suppress_message_printing(int level) { return false; } + static void printk_delay(int level) {} ++static void start_printk_kthread(struct console *con) {} + + #endif /* CONFIG_PRINTK */ + +@@ -2461,6 +2478,10 @@ void resume_console(void) + down_console_sem(); + console_suspended = 0; + console_unlock(); ++ ++ /* Wake the kthread printers. */ ++ wake_up_klogd(); ++ + pr_flush(1000, true); + } + +@@ -2676,6 +2697,10 @@ static bool console_flush_all(bool do_co + *handover = false; + + do { ++ /* Let the kthread printers do the work if they can. */ ++ if (kthread_printers_active()) ++ return false; ++ + any_progress = false; + + for_each_console(con) { +@@ -2884,6 +2909,10 @@ void console_start(struct console *conso + console_lock(); + console->flags |= CON_ENABLED; + console_unlock(); ++ ++ /* Wake the kthread printers. */ ++ wake_up_klogd(); ++ + pr_flush(1000, true); + } + EXPORT_SYMBOL(console_start); +@@ -3088,6 +3117,8 @@ void register_console(struct console *ne + /* Begin with next message. */ + newcon->seq = prb_next_seq(prb); + } ++ if (kthreads_started) ++ start_printk_kthread(newcon); + console_unlock(); + console_sysfs_notify(); + +@@ -3144,6 +3175,11 @@ int unregister_console(struct console *c + } + } + ++ if (console->thread) { ++ kthread_stop(console->thread); ++ console->thread = NULL; ++ } ++ + if (res) + goto out_disable_unlock; + +@@ -3250,6 +3286,13 @@ static int __init printk_late_init(void) + console_cpu_notify, NULL); + WARN_ON(ret < 0); + printk_sysctl_init(); ++ ++ console_lock(); ++ for_each_console(con) ++ start_printk_kthread(con); ++ kthreads_started = true; ++ console_unlock(); ++ + return 0; + } + late_initcall(printk_late_init); +@@ -3320,6 +3363,116 @@ bool pr_flush(int timeout_ms, bool reset + } + EXPORT_SYMBOL(pr_flush); + ++static bool printer_should_wake(struct console *con, u64 seq) ++{ ++ short flags; ++ ++ if (kthread_should_stop()) ++ return true; ++ ++ if (console_suspended) ++ return false; ++ ++ /* ++ * This is an unsafe read to con->flags, but false positives ++ * are not an issue as long as they are rare. ++ */ ++ flags = data_race(READ_ONCE(con->flags)); ++ if (!(flags & CON_ENABLED)) ++ return false; ++ ++ return prb_read_valid(prb, seq, NULL); ++} ++ ++static int printk_kthread_func(void *data) ++{ ++ struct console *con = data; ++ char *dropped_text = NULL; ++ char *ext_text = NULL; ++ bool progress; ++ bool handover; ++ u64 seq = 0; ++ char *text; ++ int error; ++ ++ pr_info("%sconsole [%s%d]: printing thread started\n", ++ (con->flags & CON_BOOT) ? "boot" : "", ++ con->name, con->index); ++ ++ text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL); ++ if (!text) ++ goto out; ++ ++ if (con->flags & CON_EXTENDED) { ++ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL); ++ if (!ext_text) ++ goto out; ++ } else { ++ dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL); ++ if (!dropped_text) ++ goto out; ++ } ++ ++ for (;;) { ++ error = wait_event_interruptible(log_wait, printer_should_wake(con, seq)); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ if (error) ++ continue; ++ ++ do { ++ console_lock(); ++ if (console_suspended) { ++ console_unlock(); ++ break; ++ } ++ ++ /* ++ * Even though the printk kthread is always preemptible, it is ++ * still not allowed to call cond_resched() from within ++ * console drivers. The task may become non-preemptible in the ++ * console driver call chain. For example, vt_console_print() ++ * takes a spinlock and then can call into fbcon_redraw(), ++ * which can conditionally invoke cond_resched(). ++ */ ++ console_may_schedule = 0; ++ progress = console_emit_next_record(con, text, ext_text, ++ dropped_text, &handover); ++ if (handover) ++ break; ++ ++ seq = con->seq; ++ ++ /* Unlock console without invoking direct printing. */ ++ __console_unlock(); ++ } while (progress); ++ } ++out: ++ kfree(dropped_text); ++ kfree(ext_text); ++ kfree(text); ++ pr_info("%sconsole [%s%d]: printing thread stopped\n", ++ (con->flags & CON_BOOT) ? "boot" : "", ++ con->name, con->index); ++ return 0; ++} ++ ++/* Must be called within console_lock(). */ ++static void start_printk_kthread(struct console *con) ++{ ++ con->thread = kthread_run(printk_kthread_func, con, ++ "pr/%s%d", con->name, con->index); ++ if (IS_ERR(con->thread)) { ++ con->thread = NULL; ++ pr_err("%sconsole [%s%d]: unable to start printing thread\n", ++ (con->flags & CON_BOOT) ? "boot" : "", ++ con->name, con->index); ++ return; ++ } ++} ++ + /* + * Delayed printk version, for scheduler-internal messages: + */ +@@ -3339,7 +3492,7 @@ static void wake_up_klogd_work_func(stru + } + + if (pending & PRINTK_PENDING_WAKEUP) +- wake_up_interruptible(&log_wait); ++ wake_up_interruptible_all(&log_wait); + } + + static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = |