aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-06-19 17:33:30 -0400
committerSteven Rostedt <rostedt@goodmis.org>2014-11-19 22:01:20 -0500
commit8d58e99af5980d444948720977b0976455885391 (patch)
tree1c40f6ed895112fb34b139a8bcd0e49d321fbd22 /kernel/trace
parent2448913ed2aa7a7424d9b9ca79861d13c746a3f1 (diff)
seq_buf: Move the seq_buf code to lib/
The seq_buf functions are rather useful outside of tracing. Instead of having it be dependent on CONFIG_TRACING, move the code into lib/ and allow other users to have access to it even when tracing is not configured. The seq_buf utility is similar to the seq_file utility, but instead of writing sending data back up to userland, it writes it into a buffer defined at seq_buf_init(). This allows us to send a descriptor around that writes printf() formatted strings into it that can be retrieved later. It is currently used by the tracing facility for such things like trace events to convert its binary saved data in the ring buffer into an ASCII human readable context to be displayed in /sys/kernel/debug/trace. It can also be used for doing NMI prints safely from NMI context into the seq_buf and retrieved later and dumped to printk() safely. Doing printk() from an NMI context is dangerous because an NMI can preempt a current printk() and deadlock on it. Link: http://lkml.kernel.org/p/20140619213952.058255809@goodmis.org Tested-by: Jiri Kosina <jkosina@suse.cz> Acked-by: Jiri Kosina <jkosina@suse.cz> Reviewed-by: Petr Mladek <pmladek@suse.cz> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/seq_buf.c359
2 files changed, 0 insertions, 360 deletions
<
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index edc98c72a634..67d6369ddf83 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_RING_BUFFER_BENCHMARK) += ring_buffer_benchmark.o
29obj-$(CONFIG_TRACING) += trace.o 29obj-$(CONFIG_TRACING) += trace.o
30obj-$(CONFIG_TRACING) += trace_output.o 30obj-$(CONFIG_TRACING) += trace_output.o
31obj-$(CONFIG_TRACING) += trace_seq.o 31obj-$(CONFIG_TRACING) += trace_seq.o
32obj-$(CONFIG_TRACING) += seq_buf.o
33obj-$(CONFIG_TRACING) += trace_stat.o 32obj-$(CONFIG_TRACING) += trace_stat.o
34obj-$(CONFIG_TRACING) += trace_printk.o 33obj-$(CONFIG_TRACING) += trace_printk.o
35obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o 34obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
diff --git a/kernel/trace/seq_buf.c b/kernel/trace/seq_buf.c
deleted file mode 100644
index 4eedfedb9e31..000000000000
--- a/kernel/trace/seq_buf.c
+++ /dev/null
@@ -1,359 +0,0 @@
1/*
2 * seq_buf.c
3 *
4 * Copyright (C) 2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
5 *
6 * The seq_buf is a handy tool that allows you to pass a descriptor around
7 * to a buffer that other functions can write to. It is similar to the
8 * seq_file functionality but has some differences.
9 *
10 * To use it, the seq_buf must be initialized with seq_buf_init().
11 * This will set up the counters within the descriptor. You can call
12 * seq_buf_init() more than once to reset the seq_buf to start
13 * from scratch.
14 */
15#include <linux/uaccess.h>
16#include <linux/seq_file.h>
17#include <linux/seq_buf.h>
18
19/**
20 * seq_buf_can_fit - can the new data fit in the current buffer?
21 * @s: the seq_buf descriptor
22 * @len: The length to see if it can fit in the current buffer
23 *
24 * Returns true if there's enough unused space in the seq_buf buffer
25 * to fit the amount of new data according to @len.
26 */
27static bool seq_buf_can_fit(struct seq_buf *s, size_t len)
28{
29 return s->len + len <= s->size;
30}
31
32/**
33 * seq_buf_print_seq - move the contents of seq_buf into a seq_file
34 * @m: the seq_file descriptor that is the destination
35 * @s: the seq_buf descriptor that is the source.
36 *
37 * Returns zero on success, non zero otherwise
38 */
39int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s)
40{
41 unsigned int len = seq_buf_used(s);
42
43 return seq_write(m, s->buffer, len);
44}
45
46/**
47 * seq_buf_vprintf - sequence printing of information.
48 * @s: seq_buf descriptor
49 * @fmt: printf format string
50 * @args: va_list of arguments from a printf() type function
51 *
52 * Writes a vnprintf() format into the sequencce buffer.
53 *
54 * Returns zero on success, -1 on overflow.
55 */
56int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args)
57{
58 int len;
59
60 WARN_ON(s->size == 0);
61
62 if (s->len < s->size) {
63 len = vsnprintf(s->buffer + s->len, s->size - s->len, fmt, args);
64 if (seq_buf_can_fit(s, len)) {
65 s->len += len;
66 return 0;
67 }
68 }
69 seq_buf_set_overflow(s);
70 return -1;
71}
72
73/**
74 * seq_buf_printf - sequence printing of information
75 * @s: seq_buf descriptor
76 * @fmt: printf format string
77 *
78 * Writes a printf() format into the sequence buffer.
79 *
80 * Returns zero on success, -1 on overflow.
81 */
82int seq_buf_printf(struct seq_buf *s, const char *fmt, ...)
83{
84 va_list ap;
85 int ret;
86
87 va_start(ap, fmt);
88 ret = seq_buf_vprintf(s, fmt, ap);
89 va_end(ap);
90
91 return ret;
92}
93
94/**
95 * seq_buf_bitmask - write a bitmask array in its ASCII representation
96 * @s: seq_buf descriptor
97 * @maskp: points to an array of unsigned longs that represent a bitmask
98 * @nmaskbits: The number of bits that are valid in @maskp
99 *
100 * Writes a ASCII representation of a bitmask string into @s.
101 *
102 * Returns zero on success, -1 on overflow.
103 */
104int seq_buf_bitmask(struct seq_buf *s, const unsigned long *maskp,
105 int nmaskbits)
106{
107 unsigned int len = seq_buf_buffer_left(s);
108 int ret;
109
110 WARN_ON(s->size == 0);
111
112 /*
113 * Note, because bitmap_scnprintf() only returns the number of bytes
114 * written and not the number that would be written, we use the last
115 * byte of the buffer to let us know if we overflowed. There's a small
116 * chance that the bitmap could have fit exactly inside the buffer, but
117 * it's not that critical if that does happen.
118 */
119 if (len > 1) {
120 ret = bitmap_scnprintf(s->buffer + s->len, len, maskp, nmaskbits);
121 if (ret < len) {
122 s->len += ret;
123 return 0;
124 }
125 }
126 seq_buf_set_overflow(s);
127 return -1;
128}
129
130#ifdef CONFIG_BINARY_PRINTF
131/**
132 * seq_buf_bprintf - Write the printf string from binary arguments
133 * @s: seq_buf descriptor
134 * @fmt: The format string for the @binary arguments
135 * @binary: The binary arguments for @fmt.
136 *
137 * When recording in a fast path, a printf may be recorded with just
138 * saving the format and the arguments as they were passed to the
139 * function, instead of wasting cycles converting the arguments into
140 * ASCII characters. Instead, the arguments are saved in a 32 bit
141 * word array that is defined by the format string constraints.
142 *
143 * This function will take the format and the binary array and finish
144 * the conversion into the ASCII string within the buffer.
145 *
146 * Returns zero on success, -1 on overflow.
147 */
148int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary)
149{
150 unsigned int len = seq_buf_buffer_left(s);
151 int ret;
152
153 WARN_ON(s->size == 0);
154
155 if (s->len < s->size) {
156 ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
157 if (seq_buf_can_fit(s, ret)) {
158 s->len += ret;
159 return 0;
160 }
161 }
162 seq_buf_set_overflow(s);
163 return -1;
164}
165#endif /* CONFIG_BINARY_PRINTF */
166
167/**
168 * seq_buf_puts - sequence printing of simple string
169 * @s: seq_buf descriptor
170 * @str: simple string to record
171 *
172 * Copy a simple string into the sequence buffer.
173 *
174 * Returns zero on success, -1 on overflow
175 */
176int seq_buf_puts(struct seq_buf *s, const char *str)
177{
178 unsigned int len = strlen(str);
179
180 WARN_ON(s->size == 0);
181
182 if (seq_buf_can_fit(s, len)) {
183 memcpy(s->buffer + s->len, str, len);