summaryrefslogtreecommitdiffstats
path: root/kernel/printk
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-06-19 17:33:31 -0400
committerSteven Rostedt <rostedt@goodmis.org>2014-11-19 22:01:21 -0500
commitafdc34a3d3b823a12a93b822ee1efb566f884032 (patch)
treed770a2806476751adba361918edb8826762db730 /kernel/printk
parent8d58e99af5980d444948720977b0976455885391 (diff)
printk: Add per_cpu printk func to allow printk to be diverted
Being able to divert printk to call another function besides the normal logging is useful for such things like NMI handling. If some functions are to be called from NMI that does printk() it is possible to lock up the box if the nmi handler triggers when another printk is happening. One example of this use is to perform a stack trace on all CPUs via NMI. But if the NMI is to do the printk() it can cause the system to lock up. By allowing the printk to be diverted to another function that can safely record the printk output and then print it when it in a safe context then NMIs will be safe to call these functions like show_regs(). Link: http://lkml.kernel.org/p/20140619213952.209176403@goodmis.org Tested-by: Jiri Kosina <jkosina@suse.cz> Acked-by: Jiri Kosina <jkosina@suse.cz> Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Petr Mladek <pmladek@suse.cz> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/printk')
-rw-r--r--kernel/printk/printk.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ced2b84b1cb7..f7b723f98cb9 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1807,6 +1807,30 @@ asmlinkage int printk_emit(int facility, int level,
1807} 1807}
1808EXPORT_SYMBOL(printk_emit); 1808EXPORT_SYMBOL(printk_emit);
1809 1809
1810int vprintk_default(const char *fmt, va_list args)
1811{
1812 int r;
1813
1814#ifdef CONFIG_KGDB_KDB
1815 if (unlikely(kdb_trap_printk)) {
1816 r = vkdb_printf(fmt, args);
1817 return r;
1818 }
1819#endif
1820 r = vprintk_emit(0, -1, NULL, 0, fmt, args);
1821
1822 return r;
1823}
1824EXPORT_SYMBOL_GPL(vprintk_default);
1825
1826/*
1827 * This allows printk to be diverted to another function per cpu.
1828 * This is useful for calling printk functions from within NMI
1829 * without worrying about race conditions that can lock up the
1830 * box.
1831 */
1832DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
1833
1810/** 1834/**
1811 * printk - print a kernel message 1835 * printk - print a kernel message
1812 * @fmt: format string 1836 * @fmt: format string
@@ -1830,19 +1854,15 @@ EXPORT_SYMBOL(printk_emit);
1830 */ 1854 */
1831asmlinkage __visible int printk(const char *fmt, ...) 1855asmlinkage __visible int printk(const char *fmt, ...)
1832{ 1856{
1857 printk_func_t vprintk_func;
1833 va_list args; 1858 va_list args;
1834 int r; 1859 int r;
1835 1860
1836#ifdef CONFIG_KGDB_KDB
1837 if (unlikely(kdb_trap_printk)) {
1838 va_start(args, fmt);
1839 r = vkdb_printf(fmt, args);
1840 va_end(args);
1841 return r;
1842 }
1843#endif
1844 va_start(args, fmt); 1861 va_start(args, fmt);
1845 r = vprintk_emit(0, -1, NULL, 0, fmt, args); 1862 preempt_disable();
1863 vprintk_func = this_cpu_read(printk_func);
1864 r = vprintk_func(fmt, args);
1865 preempt_enable();
1846 va_end(args); 1866 va_end(args);
1847 1867
1848 return r; 1868 return r;