On (03/24/17 10:59), Sergey Senozhatsky wrote:
[..]
> and we can jump between rescue-normal printk modes, so this should
> also return back the throttling of tasks which printk() a lot (item
> (2) in patch set cover letter) that we used to have.

ok, I obviously lied here "this should also return back the throttling".
throttling is a bit hard to implement properly.


automatic printk rescue mode on console output stall [when we can't
wake_up printk_kthread] is not so difficult. something like below.

may be it's too simple minded. // it does not handle throttling.


---
 kernel/printk/printk.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index e84b9fbb298f..005741486376 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -447,6 +447,12 @@ static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
 static char *log_buf = __log_buf;
 static u32 log_buf_len = __LOG_BUF_LEN;
 
+/*
+ * How many pending messages we can have in the logbuf before we
+ * switch to printk rescue mode (stop waking up printk_kthread).
+ */
+#define CONSOLE_STALL_MESSAGES_LIMIT   50
+
 static struct task_struct *printk_kthread __read_mostly;
 /*
  * We can't call into the scheduler (wake_up() printk kthread) during
@@ -1739,6 +1745,11 @@ static size_t log_output(int facility, int level, enum 
log_flags lflags, const c
        return log_store(facility, level, lflags, 0, dict, dictlen, text, 
text_len);
 }
 
+static bool console_output_stall(void)
+{
+       return (log_next_seq - console_seq) > CONSOLE_STALL_MESSAGES_LIMIT;
+}
+
 asmlinkage int vprintk_emit(int facility, int level,
                            const char *dict, size_t dictlen,
                            const char *fmt, va_list args)
@@ -1750,6 +1761,7 @@ asmlinkage int vprintk_emit(int facility, int level,
        unsigned long flags;
        int printed_len = 0;
        bool in_sched = false;
+       bool printk_stall;
 
        if (level == LOGLEVEL_SCHED) {
                level = LOGLEVEL_DEFAULT;
@@ -1811,6 +1823,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 
        printed_len += log_output(facility, level, lflags, dict, dictlen, text, 
text_len);
 
+       printk_stall = console_output_stall();
        set_bit(PRINTK_PENDING_OUTPUT, &printk_pending);
        logbuf_unlock_irqrestore(flags);
 
@@ -1824,7 +1837,7 @@ asmlinkage int vprintk_emit(int facility, int level,
                 * from a dedicated printk_kthread, which always runs in
                 * schedulable context.
                 */
-               if (printk_kthread_enabled()) {
+               if (!printk_stall && printk_kthread_enabled()) {
                        printk_safe_enter_irqsave(flags);
                        wake_up_process(printk_kthread);
                        printk_safe_exit_irqrestore(flags);
-- 
2.12.1

Reply via email to