As of now we don't `offload' printing from printk_kthread and print all pending logbuf messages. This, however, may have a negative effect. We still hold console_sem as long as we have got messages to print, and there might be other console_lock() callers sleeping on console_sem in TASK_UNINTERRUPTIBLE, including user space processes (tty_open, drm IOCTL, etc.).
A bigger issue is that we still can schedule with console_sem locked, which is not right and we want to avoid it. This patch also serves as a preparation for preemption disabled printing loop. So we need to up() console_sem every once in a while, even if current console_sem owner is printk_kthread, just in order to wake up those other processes that can sleep on console_sem. If there are no tasks sleeping on console_sem, then printk_kthread will immediately return back to console_unclok(), because we don't clear the PRINTK_PENDING_OUTPUT bit and printk_kthread checks it before it decides to schedule(). Signed-off-by: Sergey Senozhatsky <[email protected]> --- kernel/printk/printk.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 372c71f69e8e..4d91182e25e3 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -586,14 +586,27 @@ static inline bool should_handoff_printing(u64 printing_start_ts) if (time_after_eq64(now, printing_start_ts)) printing_elapsed += now - printing_start_ts; - /* Once we offloaded to printk_ktread - keep printing */ - if (current == printk_kthread) - return false; - /* Shrink down to seconds and check the offloading threshold */ if ((printing_elapsed >> 30LL) < offloading_threshold()) return false; + if (current == printk_kthread) { + /* + * All tasks must offload - we don't want to keep console_sem + * locked for too long. However, printk_kthread may be the + * only process left willing to down(). So we may return back + * immediately after we leave, because PRINTK_PENDING_OUTPUT + * bit is still set and printk_kthread_func() won't schedule. + * This still counts as offloading, so reset the stats. + * + * Should `printk_kthread' immediately return back to + * console_unlock(), it will have another full + * `offloading_threshold()' time slice. + */ + printing_elapsed = 0; + return true; + } + /* * We try to set `printk_kthread' CPU affinity to any online CPU * except for this_cpu. Because otherwise `printk_kthread' may be -- 2.15.1

