aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 23:35:41 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 23:35:41 -0500
commit350e4f4985472e29091b899bc227d75d2a66fb4c (patch)
tree98d17fe2198025d55511d7a306a787b76c3dde4f /kernel/printk
parentc32809521de5b31699a33379183848b0c7628f28 (diff)
parentdb0865543739b3edb2ee9bf340380cf4986b58ff (diff)
Merge tag 'trace-seq-buf-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull nmi-safe seq_buf printk update from Steven Rostedt: "This code is a fork from the trace-3.19 pull as it needed the trace_seq clean ups from that branch. This code solves the issue of performing stack dumps from NMI context. The issue is that printk() is not safe from NMI context as if the NMI were to trigger when a printk() was being performed, the NMI could deadlock from the printk() internal locks. This has been seen in practice. With lots of review from Petr Mladek, this code went through several iterations, and we feel that it is now at a point of quality to be accepted into mainline. Here's what is contained in this patch set: - Creates a "seq_buf" generic buffer utility that allows a descriptor to be passed around where functions can write their own "printk()" formatted strings into it. The generic version was pulled out of the trace_seq() code that was made specifically for tracing. - The seq_buf code was change to model the seq_file code. I have a patch (not included for 3.19) that converts the seq_file.c code over to use seq_buf.c like the trace_seq.c code does. This was done to make sure that seq_buf.c is compatible with seq_file.c. I may try to get that patch in for 3.20. - The seq_buf.c file was moved to lib/ to remove it from being dependent on CONFIG_TRACING. - The printk() was updated to allow for a per_cpu "override" of the internal calls. That is, instead of writing to the console, a call to printk() may do something else. This made it easier to allow the NMI to change what printk() does in order to call dump_stack() without needing to update that code as well. - Finally, the dump_stack from all CPUs via NMI code was converted to use the seq_buf code. The caller to trigger the NMI code would wait till all the NMIs finished, and then it would print the seq_buf data to the console safely from a non NMI context One added bonus is that this code also makes the NMI dump stack work on PREEMPT_RT kernels. As printk() includes sleeping locks on PREEMPT_RT, printk() only writes to console if the console does not use any rt_mutex converted spin locks. Which a lot do" * tag 'trace-seq-buf-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: x86/nmi: Fix use of unallocated cpumask_var_t printk/percpu: Define printk_func when printk is not defined x86/nmi: Perform a safe NMI stack trace on all CPUs printk: Add per_cpu printk func to allow printk to be diverted seq_buf: Move the seq_buf code to lib/ seq-buf: Make seq_buf_bprintf() conditional on CONFIG_BINARY_PRINTF tracing: Add seq_buf_get_buf() and seq_buf_commit() helper functions tracing: Have seq_buf use full buffer seq_buf: Add seq_buf_can_fit() helper function tracing: Add paranoid size check in trace_printk_seq() tracing: Use trace_seq_used() and seq_buf_used() instead of len tracing: Clean up tracing_fill_pipe_page() seq_buf: Create seq_buf_used() to find out how much was written tracing: Add a seq_buf_clear() helper and clear len and readpos in init tracing: Convert seq_buf fields to be like seq_file fields tracing: Convert seq_buf_path() to be like seq_path() tracing: Create seq_buf layer in trace_seq
Diffstat (limited to 'kernel/printk')
-rw-r--r--kernel/printk/printk.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ea27c019655a..f900dc9f6822 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1805,6 +1805,30 @@ asmlinkage int printk_emit(int facility, int level,
1805} 1805}
1806EXPORT_SYMBOL(printk_emit); 1806EXPORT_SYMBOL(printk_emit);
1807 1807
1808int vprintk_default(const char *fmt, va_list args)
1809{
1810 int r;
1811
1812#ifdef CONFIG_KGDB_KDB
1813 if (unlikely(kdb_trap_printk)) {
1814 r = vkdb_printf(fmt, args);
1815 return r;
1816 }
1817#endif
1818 r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
1819
1820 return r;
1821}
1822EXPORT_SYMBOL_GPL(vprintk_default);
1823
1824/*
1825 * This allows printk to be diverted to another function per cpu.
1826 * This is useful for calling printk functions from within NMI
1827 * without worrying about race conditions that can lock up the
1828 * box.
1829 */
1830DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
1831
1808/** 1832/**
1809 * printk - print a kernel message 1833 * printk - print a kernel message
1810 * @fmt: format string 1834 * @fmt: format string
@@ -1828,19 +1852,15 @@ EXPORT_SYMBOL(printk_emit);
1828 */ 1852 */
1829asmlinkage __visible int printk(const char *fmt, ...) 1853asmlinkage __visible int printk(const char *fmt, ...)
1830{ 1854{
1855 printk_func_t vprintk_func;
1831 va_list args; 1856 va_list args;
1832 int r; 1857 int r;
1833 1858
1834#ifdef CONFIG_KGDB_KDB
1835 if (unlikely(kdb_trap_printk)) {
1836 va_start(args, fmt);
1837 r = vkdb_printf(fmt, args);
1838 va_end(args);
1839 return r;
1840 }
1841#endif
1842 va_start(args, fmt); 1859 va_start(args, fmt);
1843 r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args); 1860 preempt_disable();
1861 vprintk_func = this_cpu_read(printk_func);
1862 r = vprintk_func(fmt, args);
1863 preempt_enable();
1844 va_end(args); 1864 va_end(args);
1845 1865
1846 return r; 1866 return r;
@@ -1874,6 +1894,9 @@ static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
1874 bool syslog, char *buf, size_t size) { return 0; } 1894 bool syslog, char *buf, size_t size) { return 0; }
1875static size_t cont_print_text(char *text, size_t size) { return 0; } 1895static size_t cont_print_text(char *text, size_t size) { return 0; }
1876 1896
1897/* Still needs to be defined for users */
1898DEFINE_PER_CPU(printk_func_t, printk_func);
1899
1877#endif /* CONFIG_PRINTK */ 1900#endif /* CONFIG_PRINTK */
1878 1901
1879#ifdef CONFIG_EARLY_PRINTK 1902#ifdef CONFIG_EARLY_PRINTK