[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20170413081955.GA424@jagdpanzerIV.localdomain>
Date: Thu, 13 Apr 2017 17:19:55 +0900
From: Sergey Senozhatsky <sergey.senozhatsky.work@...il.com>
To: Petr Mladek <pmladek@...e.com>, Pavel Machek <pavel@....cz>
Cc: Jan Kara <jack@...e.cz>,
"Eric W. Biederman" <ebiederm@...ssion.com>,
Ye Xiaolong <xiaolong.ye@...el.com>,
Steven Rostedt <rostedt@...dmis.org>,
Andrew Morton <akpm@...ux-foundation.org>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Peter Zijlstra <peterz@...radead.org>,
"Rafael J . Wysocki" <rjw@...ysocki.net>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Jiri Slaby <jslaby@...e.com>, Len Brown <len.brown@...el.com>,
linux-kernel@...r.kernel.org,
Sergey Senozhatsky <sergey.senozhatsky@...il.com>,
Sergey Senozhatsky <sergey.senozhatsky.work@...il.com>
Subject: Re: [printk] fbc14616f4:
BUG:kernel_reboot-without-warning_in_test_stage
On (04/13/17 14:50), Sergey Senozhatsky wrote:
[..]
> On (04/12/17 01:19), Sergey Senozhatsky wrote:
> [..]
> > it does offloading after X printed lines by the same process.
> > if we reschedule, then the counter resets. which is probably OK,
> > we don't really want any process, except for printk_kthread, to
> > stay in console_unlock() forever.
>
> may be this can be changed. we don't want even printk_kthread to keep
> console_sem locked for too long, because other process that might want
> to lock console_sem have to sleep in TASK_UNINTERRUPTIBLE as long as
> printing thread has pending messages to print. so may be the rule can
> be "every process prints up to `atomic_print_limit' lines and then
> offloads printing - wake_up()s printk_kthread and up()s console_sem".
> some other process (printk_kthread or a process from console_sem wait
> list, let them compete for console_sem) will eventually down()
> console_sem and print the next `atomic_print_limit' lines, while
> current process will have a chance to return from console_unlock() and
> do something else.
something like this, perhaps.
static inline bool console_offload_printing(void)
{
static struct task_struct *printing_task;
static unsigned long lines_printed;
static bool did_wakeup;
if (!atomic_print_limit || !printk_kthread_enabled())
return false;
/* We rescheduled - reset the counters. */
if (printing_task != current) {
did_wakeup = false;
lines_printed = 0;
printing_task = current;
return false;
}
/*
* Don't reset the counter, let CPU overrun the limit.
* The idea is that
*
* a) woken up printk_kthread (if succeeded)
* or
* b) concurrent printk from another CPU (if any)
*
* will change `printing_task' and reset the counter.
* If neither a) nor b) happens - we continue printing from
* current process. Which is bad and can be risky, but we can't
* wake_up() printk_kthread, so things already don't look normal.
*/
lines_printed++;
if (lines_printed < atomic_print_limit)
return false;
if (current == printk_kthread) {
/*
* Reset the counter, just in case if printk_kthread is the
* only process left that would down() console_sem.
*/
lines_printed = 0;
return true;
}
/*
* A trivial emergency enforcement - give up on printk_kthread if
* we can't wake it up. This assumes that `atomic_print_limit' is
* large enough.
*/
if (lines_printed > 2 * (unsigned long long)atomic_print_limit) {
printk_enforce_emergency = true;
pr_crit("Declaring printk emergency mode.\n");
return false;
}
/*
* Must be executed in 'printk_safe' context. Call into the
* scheduler just once, in case if it backfires on us with
* warnings and backtraces.
*/
if (!did_wakeup) {
did_wakeup = true;
wake_up_process(printk_kthread);
}
return true;
}
-ss
Powered by blists - more mailing lists