aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergey Senozhatsky <sergey.senozhatsky.work@gmail.com>2018-01-15 23:47:16 -0500
committerPetr Mladek <pmladek@suse.com>2018-01-16 11:21:28 -0500
commitfd5f7cde1b85d4c8e09ca46ce948e008a2377f64 (patch)
treeb83fe26657e46956d96a307214e249b16f47fc04
parentc162d5b4338d72deed61aa65ed0f2f4ba2bbc8ab (diff)
printk: Never set console_may_schedule in console_trylock()
This patch, basically, reverts commit 6b97a20d3a79 ("printk: set may_schedule for some of console_trylock() callers"). That commit was a mistake, it introduced a big dependency on the scheduler, by enabling preemption under console_sem in printk()->console_unlock() path, which is rather too critical. The patch did not significantly reduce the possibilities of printk() lockups, but made it possible to stall printk(), as has been reported by Tetsuo Handa [1]. Another issues is that preemption under console_sem also messes up with Steven Rostedt's hand off scheme, by making it possible to sleep with console_sem both in console_unlock() and in vprintk_emit(), after acquiring the console_sem ownership (anywhere between printk_safe_exit_irqrestore() in console_trylock_spinning() and printk_safe_enter_irqsave() in console_unlock()). This makes hand off less likely and, at the same time, may result in a significant amount of pending logbuf messages. Preempted console_sem owner makes it impossible for other CPUs to emit logbuf messages, but does not make it impossible for other CPUs to append new messages to the logbuf. Reinstate the old behavior and make printk() non-preemptible. Should any printk() lockup reports arrive they must be handled in a different way. [1] http://lkml.kernel.org/r/201603022101.CAH73907.OVOOMFHFFtQJSL%20()%20I-love%20!%20SAKURA%20!%20ne%20!%20jp Fixes: 6b97a20d3a79 ("printk: set may_schedule for some of console_trylock() callers") Link: http://lkml.kernel.org/r/20180116044716.GE6607@jagdpanzerIV To: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Tejun Heo <tj@kernel.org> Cc: akpm@linux-foundation.org Cc: linux-mm@kvack.org Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Michal Hocko <mhocko@kernel.org> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Jan Kara <jack@suse.cz> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Byungchul Park <byungchul.park@lge.com> Cc: Pavel Machek <pavel@ucw.cz> Cc: linux-kernel@vger.kernel.org Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Signed-off-by: Petr Mladek <pmladek@suse.com>
-rw-r--r--kernel/printk/printk.c22
1 files changed, 8 insertions, 14 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 3a475f58b749..6b9d8d56e0e2 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1889,12 +1889,19 @@ asmlinkage int vprintk_emit(int facility, int level,
1889 /* If called from the scheduler, we can not call up(). */ 1889 /* If called from the scheduler, we can not call up(). */
1890 if (!in_sched) { 1890 if (!in_sched) {
1891 /* 1891 /*
1892 * Disable preemption to avoid being preempted while holding
1893 * console_sem which would prevent anyone from printing to
1894 * console
1895 */
1896 preempt_disable();
1897 /*
1892 * Try to acquire and then immediately release the console 1898 * Try to acquire and then immediately release the console
1893 * semaphore. The release will print out buffers and wake up 1899 * semaphore. The release will print out buffers and wake up
1894 * /dev/kmsg and syslog() users. 1900 * /dev/kmsg and syslog() users.
1895 */ 1901 */
1896 if (console_trylock_spinning()) 1902 if (console_trylock_spinning())
1897 console_unlock(); 1903 console_unlock();
1904 preempt_enable();
1898 } 1905 }
1899 1906
1900 return printed_len; 1907 return printed_len;
@@ -2211,20 +2218,7 @@ int console_trylock(void)
2211 return 0; 2218 return 0;
2212 } 2219 }
2213 console_locked = 1; 2220 console_locked = 1;
2214 /* 2221 console_may_schedule = 0;
2215 * When PREEMPT_COUNT disabled we can't reliably detect if it's
2216 * safe to schedule (e.g. calling printk while holding a spin_lock),
2217 * because preempt_disable()/preempt_enable() are just barriers there
2218 * and preempt_count() is always 0.
2219 *
2220 * RCU read sections have a separate preemption counter when
2221 * PREEMPT_RCU enabled thus we must take extra care and check
2222 * rcu_preempt_depth(), otherwise RCU read sections modify
2223 * preempt_count().
2224 */
2225 console_may_schedule = !oops_in_progress &&
2226 preemptible() &&
2227 !rcu_preempt_depth();
2228 return 1; 2222 return 1;
2229} 2223}
2230EXPORT_SYMBOL(console_trylock); 2224EXPORT_SYMBOL(console_trylock);