aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/seq_buf.h81
-rw-r--r--include/linux/trace_seq.h12
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/seq_buf.c341
-rw-r--r--kernel/trace/trace.c39
-rw-r--r--kernel/trace/trace_events.c6
-rw-r--r--kernel/trace/trace_functions_graph.c6
-rw-r--r--kernel/trace/trace_seq.c178
8 files changed, 538 insertions, 126 deletions
diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h
new file mode 100644
index 000000000000..4f7a96a9d71a
--- /dev/null
+++ b/include/linux/seq_buf.h
@@ -0,0 +1,81 @@
1#ifndef _LINUX_SEQ_BUF_H
2#define _LINUX_SEQ_BUF_H
3
4#include <linux/fs.h>
5
6/*
7 * Trace sequences are used to allow a function to call several other functions
8 * to create a string of data to use.
9 */
10
11/**
12 * seq_buf - seq buffer structure
13 * @buffer: pointer to the buffer
14 * @size: size of the buffer
15 * @len: the amount of data inside the buffer
16 * @readpos: The next position to read in the buffer.
17 */
18struct seq_buf {
19 unsigned char *buffer;
20 unsigned int size;
21 unsigned int len;
22 unsigned int readpos;
23};
24
25static inline void
26seq_buf_init(struct seq_buf *s, unsigned char *buf, unsigned int size)
27{
28 s->buffer = buf;
29 s->size = size;
30 s->len = 0;
31 s->readpos = 0;
32}
33
34/*
35 * seq_buf have a buffer that might overflow. When this happens
36 * the len and size are set to be equal.
37 */
38static inline bool
39seq_buf_has_overflowed(struct seq_buf *s)
40{
41 return s->len == s->size;
42}
43
44static inline void
45seq_buf_set_overflow(struct seq_buf *s)
46{
47 s->len = s->size;
48}
49
50/*
51 * How much buffer is left on the seq_buf?
52 */
53static inline unsigned int
54seq_buf_buffer_left(struct seq_buf *s)
55{
56 if (seq_buf_has_overflowed(s))
57 return 0;
58
59 return (s->size - 1) - s->len;
60}
61
62extern __printf(2, 3)
63int seq_buf_printf(struct seq_buf *s, const char *fmt, ...);
64extern __printf(2, 0)
65int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args);
66extern int
67seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary);
68extern int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s);
69extern int seq_buf_to_user(struct seq_buf *s, char __user *ubuf,
70 int cnt);
71extern int seq_buf_puts(struct seq_buf *s, const char *str);
72extern int seq_buf_putc(struct seq_buf *s, unsigned char c);
73extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len);
74extern int seq_buf_putmem_hex(struct seq_buf *s, const void *mem,
75 unsigned int len);
76extern int seq_buf_path(struct seq_buf *s, const struct path *path);
77
78extern int seq_buf_bitmask(struct seq_buf *s, const unsigned long *maskp,
79 int nmaskbits);
80
81#endif /* _LINUX_SEQ_BUF_H */
diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h
index db8a73224f1a..85d37106be3d 100644
--- a/include/linux/trace_seq.h
+++ b/include/linux/trace_seq.h
@@ -1,7 +1,7 @@
1#ifndef _LINUX_TRACE_SEQ_H 1#ifndef _LINUX_TRACE_SEQ_H
2#define _LINUX_TRACE_SEQ_H 2#define _LINUX_TRACE_SEQ_H
3 3
4#include <linux/fs.h> 4#include <linux/seq_buf.h>
5 5
6#include <asm/page.h> 6#include <asm/page.h>
7 7
@@ -12,16 +12,14 @@
12 12
13struct trace_seq { 13struct trace_seq {
14 unsigned char buffer[PAGE_SIZE]; 14 unsigned char buffer[PAGE_SIZE];
15 unsigned int len; 15 struct seq_buf seq;
16 unsigned int readpos;
17 int full; 16 int full;
18}; 17};
19 18
20static inline void 19static inline void
21trace_seq_init(struct trace_seq *s) 20trace_seq_init(struct trace_seq *s)
22{ 21{
23 s->len = 0; 22 seq_buf_init(&s->seq, s->buffer, PAGE_SIZE);
24 s->readpos = 0;
25 s->full = 0; 23 s->full = 0;
26} 24}
27 25
@@ -37,7 +35,7 @@ trace_seq_init(struct trace_seq *s)
37static inline unsigned char * 35static inline unsigned char *
38trace_seq_buffer_ptr(struct trace_seq *s) 36trace_seq_buffer_ptr(struct trace_seq *s)
39{ 37{
40 return s->buffer + s->len; 38 return s->buffer + s->seq.len;
41} 39}
42 40
43/** 41/**
@@ -49,7 +47,7 @@ trace_seq_buffer_ptr(struct trace_seq *s)
49 */ 47 */
50static inline bool trace_seq_has_overflowed(struct trace_seq *s) 48static inline bool trace_seq_has_overflowed(struct trace_seq *s)
51{ 49{
52 return s->full || s->len > PAGE_SIZE - 1; 50 return s->full || seq_buf_has_overflowed(&s->seq);
53} 51}
54 52
55/* 53/*
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 67d6369ddf83..edc98c72a634 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -29,6 +29,7 @@ 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
32obj-$(CONFIG_TRACING) += trace_stat.o 33obj-$(CONFIG_TRACING) += trace_stat.o
33obj-$(CONFIG_TRACING) += trace_printk.o 34obj-$(CONFIG_TRACING) += trace_printk.o
34obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o 35obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
diff --git a/kernel/trace/seq_buf.c b/kernel/trace/seq_buf.c
new file mode 100644
index 000000000000..e9a7861595d2
--- /dev/null
+++ b/kernel/trace/seq_buf.c
@@ -0,0 +1,341 @@
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/* How much buffer is written? */
20#define SEQ_BUF_USED(s) min((s)->len, (s)->size - 1)
21
22/**
23 * seq_buf_print_seq - move the contents of seq_buf into a seq_file
24 * @m: the seq_file descriptor that is the destination
25 * @s: the seq_buf descriptor that is the source.
26 *
27 * Returns zero on success, non zero otherwise
28 */
29int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s)
30{
31 unsigned int len = SEQ_BUF_USED(s);
32
33 return seq_write(m, s->buffer, len);
34}
35
36/**
37 * seq_buf_vprintf - sequence printing of information.
38 * @s: seq_buf descriptor
39 * @fmt: printf format string
40 * @args: va_list of arguments from a printf() type function
41 *
42 * Writes a vnprintf() format into the sequencce buffer.
43 *
44 * Returns zero on success, -1 on overflow.
45 */
46int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args)
47{
48 int len;
49
50 WARN_ON(s->size == 0);
51
52 if (s->len < s->size) {
53 len = vsnprintf(s->buffer + s->len, s->size - s->len, fmt, args);
54 if (s->len + len < s->size) {
55 s->len += len;
56 return 0;
57 }
58 }
59 seq_buf_set_overflow(s);
60 return -1;
61}
62
63/**
64 * seq_buf_printf - sequence printing of information
65 * @s: seq_buf descriptor
66 * @fmt: printf format string
67 *
68 * Writes a printf() format into the sequence buffer.
69 *
70 * Returns zero on success, -1 on overflow.
71 */
72int seq_buf_printf(struct seq_buf *s, const char *fmt, ...)
73{
74 va_list ap;
75 int ret;
76
77 va_start(ap, fmt);
78 ret = seq_buf_vprintf(s, fmt, ap);
79 va_end(ap);
80
81 return ret;
82}
83
84/**
85 * seq_buf_bitmask - write a bitmask array in its ASCII representation
86 * @s: seq_buf descriptor
87 * @maskp: points to an array of unsigned longs that represent a bitmask
88 * @nmaskbits: The number of bits that are valid in @maskp
89 *
90 * Writes a ASCII representation of a bitmask string into @s.
91 *
92 * Returns zero on success, -1 on overflow.
93 */
94int seq_buf_bitmask(struct seq_buf *s, const unsigned long *maskp,
95 int nmaskbits)
96{
97 unsigned int len = seq_buf_buffer_left(s);
98 int ret;
99
100 WARN_ON(s->size == 0);
101
102 /*
103 * The last byte of the buffer is used to determine if we
104 * overflowed or not.
105 */
106 if (len > 1) {
107 ret = bitmap_scnprintf(s->buffer + s->len, len, maskp, nmaskbits);
108 if (ret < len) {
109 s->len += ret;
110 return 0;
111 }
112 }
113 seq_buf_set_overflow(s);
114 return -1;
115}
116
117/**
118 * seq_buf_bprintf - Write the printf string from binary arguments
119 * @s: seq_buf descriptor
120 * @fmt: The format string for the @binary arguments
121 * @binary: The binary arguments for @fmt.
122 *
123 * When recording in a fast path, a printf may be recorded with just
124 * saving the format and the arguments as they were passed to the
125 * function, instead of wasting cycles converting the arguments into
126 * ASCII characters. Instead, the arguments are saved in a 32 bit
127 * word array that is defined by the format string constraints.
128 *
129 * This function will take the format and the binary array and finish
130 * the conversion into the ASCII string within the buffer.
131 *
132 * Returns zero on success, -1 on overflow.
133 */
134int seq_buf_bprintf(struct seq_buf *s, const char *fmt, const u32 *binary)
135{
136 unsigned int len = seq_buf_buffer_left(s);
137 int ret;
138
139 WARN_ON(s->size == 0);
140
141 if (s->len < s->size) {
142 ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
143 if (s->len + ret < s->size) {
144 s->len += ret;
145 return 0;
146 }
147 }
148 seq_buf_set_overflow(s);
149 return -1;
150}
151
152/**
153 * seq_buf_puts - sequence printing of simple string
154 * @s: seq_buf descriptor
155 * @str: simple string to record
156 *
157 * Copy a simple string into the sequence buffer.
158 *
159 * Returns zero on success, -1 on overflow
160 */
161int seq_buf_puts(struct seq_buf *s, const char *str)
162{
163 unsigned int len = strlen(str);
164
165 WARN_ON(s->size == 0);
166
167 if (s->len + len < s->size) {
168 memcpy(s->buffer + s->len, str, len);
169 s->len += len;
170 return 0;
171 }
172 seq_buf_set_overflow(s);
173 return -1;
174}
175
176/**
177 * seq_buf_putc - sequence printing of simple character
178 * @s: seq_buf descriptor
179 * @c: simple character to record
180 *
181 * Copy a single character into the sequence buffer.
182 *
183 * Returns zero on success, -1 on overflow
184 */
185int seq_buf_putc(struct seq_buf *s, unsigned char c)
186{
187 WARN_ON(s->size == 0);
188
189 if (s->len + 1 < s->size) {
190 s->buffer[s->len++] = c;
191 return 0;
192 }
193 seq_buf_set_overflow(s);
194 return -1;
195}
196
197/**
198 * seq_buf_putmem - write raw data into the sequenc buffer
199 * @s: seq_buf descriptor
200 * @mem: The raw memory to copy into the buffer
201 * @len: The length of the raw memory to copy (in bytes)
202 *
203 * There may be cases where raw memory needs to be written into the
204 * buffer and a strcpy() would not work. Using this function allows
205 * for such cases.
206 *
207 * Returns zero on success, -1 on overflow
208 */
209int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len)
210{
211 WARN_ON(s->size == 0);
212
213 if (s->len + len < s->size) {
214 memcpy(s->buffer + s->len, mem, len);
215 s->len += len;
216 return 0;
217 }
218 seq_buf_set_overflow(s);
219 return -1;
220}
221
222#define MAX_MEMHEX_BYTES 8U
223#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)
224
225/**
226 * seq_buf_putmem_hex - write raw memory into the buffer in ASCII hex
227 * @s: seq_buf descriptor
228 * @mem: The raw memory to write its hex ASCII representation of
229 * @len: The length of the raw memory to copy (in bytes)
230 *
231 * This is similar to seq_buf_putmem() except instead of just copying the
232 * raw memory into the buffer it writes its ASCII representation of it
233 * in hex characters.
234 *
235 * Returns zero on success, -1 on overflow
236 */
237int seq_buf_putmem_hex(struct seq_buf *s, const void *mem,
238 unsigned int len)
239{
240 unsigned char hex[HEX_CHARS];
241 const unsigned char *data = mem;
242 unsigned int start_len;
243 int i, j;
244
245 WARN_ON(s->size == 0);
246
247 while (len) {
248 start_len = min(len, HEX_CHARS - 1);
249#ifdef __BIG_ENDIAN
250 for (i = 0, j = 0; i < start_len; i++) {
251#else
252 for (i = start_len-1, j = 0; i >= 0; i--) {
253#endif
254 hex[j++] = hex_asc_hi(data[i]);
255 hex[j++] = hex_asc_lo(data[i]);
256 }
257 if (WARN_ON_ONCE(j == 0 || j/2 > len))
258 break;
259
260 /* j increments twice per loop */
261 len -= j / 2;
262 hex[j++] = ' ';
263
264 seq_buf_putmem(s, hex, j);
265 if (seq_buf_has_overflowed(s))
266 return -1;
267 }
268 return 0;
269}
270
271/**
272 * seq_buf_path - copy a path into the sequence buffer
273 * @s: seq_buf descriptor
274 * @path: path to write into the sequence buffer.
275 *
276 * Write a path name into the sequence buffer.
277 *
278 * Returns zero on success, -1 on overflow
279 */
280int seq_buf_path(struct seq_buf *s, const struct path *path)
281{
282 unsigned int len = seq_buf_buffer_left(s);
283 unsigned char *p;
284
285 WARN_ON(s->size == 0);
286
287 p = d_path(path, s->buffer + s->len, len);
288 if (!IS_ERR(p)) {
289 p = mangle_path(s->buffer + s->len, p, "\n");
290 if (p) {
291 s->len = p - s->buffer;
292 return 0;
293 }
294 }
295 seq_buf_set_overflow(s);
296 return -1;
297}
298
299/**
300 * seq_buf_to_user - copy the squence buffer to user space
301 * @s: seq_buf descriptor
302 * @ubuf: The userspace memory location to copy to
303 * @cnt: The amount to copy
304 *
305 * Copies the sequence buffer into the userspace memory pointed to
306 * by @ubuf. It starts from the last read position (@s->readpos)
307 * and writes up to @cnt characters or till it reaches the end of
308 * the content in the buffer (@s->len), which ever comes first.
309 *
310 * On success, it returns a positive number of the number of bytes
311 * it copied.
312 *
313 * On failure it returns -EBUSY if all of the content in the
314 * sequence has been already read, which includes nothing in the
315 * sequence (@s->len == @s->readpos).
316 *
317 * Returns -EFAULT if the copy to userspace fails.
318 */
319int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt)
320{
321 int len;
322 int ret;
323
324 if (!cnt)
325 return 0;
326
327 if (s->len <= s->readpos)
328 return -EBUSY;
329
330 len = s->len - s->readpos;
331 if (cnt > len)
332 cnt = len;
333 ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
334 if (ret == cnt)
335 return -EFAULT;
336
337 cnt -= ret;
338
339 s->readpos += cnt;
340 return cnt;
341}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 3ce3c4ccfc94..7d7a07e9b9e9 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -939,19 +939,20 @@ out:
939 return ret; 939 return ret;
940} 940}
941 941
942/* TODO add a seq_buf_to_buffer() */
942static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt) 943static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
943{ 944{
944 int len; 945 int len;
945 946
946 if (s->len <= s->readpos) 947 if (s->seq.len <= s->seq.readpos)
947 return -EBUSY; 948 return -EBUSY;
948 949
949 len = s->len - s->readpos; 950 len = s->seq.len - s->seq.readpos;
950 if (cnt > len) 951 if (cnt > len)
951 cnt = len; 952 cnt = len;
952 memcpy(buf, s->buffer + s->readpos, cnt); 953 memcpy(buf, s->buffer + s->seq.readpos, cnt);
953 954
954 s->readpos += cnt; 955 s->seq.readpos += cnt;
955 return cnt; 956 return cnt;
956} 957}
957 958
@@ -4315,6 +4316,8 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
4315 goto out; 4316 goto out;
4316 } 4317 }
4317 4318
4319 trace_seq_init(&iter->seq);
4320
4318 /* 4321 /*
4319 * We make a copy of the current tracer to avoid concurrent 4322 * We make a copy of the current tracer to avoid concurrent
4320 * changes on it while we are reading. 4323 * changes on it while we are reading.
@@ -4511,18 +4514,18 @@ waitagain:
4511 trace_access_lock(iter->cpu_file); 4514 trace_access_lock(iter->cpu_file);
4512 while (trace_find_next_entry_inc(iter) != NULL) { 4515 while (trace_find_next_entry_inc(iter) != NULL) {
4513 enum print_line_t ret; 4516 enum print_line_t ret;
4514 int len = iter->seq.len; 4517 int len = iter->seq.seq.len;
4515 4518
4516 ret = print_trace_line(iter); 4519 ret = print_trace_line(iter);
4517 if (ret == TRACE_TYPE_PARTIAL_LINE) { 4520 if (ret == TRACE_TYPE_PARTIAL_LINE) {
4518 /* don't print partial lines */ 4521 /* don't print partial lines */
4519 iter->seq.len = len; 4522 iter->seq.seq.len = len;
4520 break; 4523 break;
4521 } 4524 }
4522 if (ret != TRACE_TYPE_NO_CONSUME) 4525 if (ret != TRACE_TYPE_NO_CONSUME)
4523 trace_consume(iter); 4526 trace_consume(iter);
4524 4527
4525 if (iter->seq.len >= cnt) 4528 if (iter->seq.seq.len >= cnt)
4526 break; 4529 break;
4527 4530
4528 /* 4531 /*
@@ -4538,7 +4541,7 @@ waitagain:
4538 4541
4539 /* Now copy what we have to the user */ 4542 /* Now copy what we have to the user */
4540 sret = trace_seq_to_user(&iter->seq, ubuf, cnt); 4543 sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
4541 if (iter->seq.readpos >= iter->seq.len) 4544 if (iter->seq.seq.readpos >= iter->seq.seq.len)
4542 trace_seq_init(&iter->seq); 4545 trace_seq_init(&iter->seq);
4543 4546
4544 /* 4547 /*
@@ -4576,16 +4579,16 @@ tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter)
4576 4579
4577 /* Seq buffer is page-sized, exactly what we need. */ 4580 /* Seq buffer is page-sized, exactly what we need. */
4578 for (;;) { 4581 for (;;) {
4579 count = iter->seq.len; 4582 count = iter->seq.seq.len;
4580 ret = print_trace_line(iter); 4583 ret = print_trace_line(iter);
4581 count = iter->seq.len - count; 4584 count = iter->seq.seq.len - count;
4582 if (rem < count) { 4585 if (rem < count) {
4583 rem = 0; 4586 rem = 0;
4584 iter->seq.len -= count; 4587 iter->seq.seq.len -= count;
4585 break; 4588 break;
4586 } 4589 }
4587 if (ret == TRACE_TYPE_PARTIAL_LINE) { 4590 if (ret == TRACE_TYPE_PARTIAL_LINE) {
4588 iter->seq.len -= count; 4591 iter->seq.seq.len -= count;
4589 break; 4592 break;
4590 } 4593 }
4591 4594
@@ -4666,13 +4669,13 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
4666 /* Copy the data into the page, so we can start over. */ 4669 /* Copy the data into the page, so we can start over. */
4667 ret = trace_seq_to_buffer(&iter->seq, 4670 ret = trace_seq_to_buffer(&iter->seq,
4668 page_address(spd.pages[i]), 4671 page_address(spd.pages[i]),
4669 iter->seq.len); 4672 iter->seq.seq.len);
4670 if (ret < 0) { 4673 if (ret < 0) {
4671 __free_page(spd.pages[i]); 4674 __free_page(spd.pages[i]);
4672 break; 4675 break;
4673 } 4676 }
4674 spd.partial[i].offset = 0; 4677 spd.partial[i].offset = 0;
4675 spd.partial[i].len = iter->seq.len; 4678 spd.partial[i].len = iter->seq.seq.len;
4676 4679
4677 trace_seq_init(&iter->seq); 4680 trace_seq_init(&iter->seq);
4678 } 4681 }
@@ -5673,7 +5676,7 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
5673 cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu); 5676 cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu);
5674 trace_seq_printf(s, "read events: %ld\n", cnt); 5677 trace_seq_printf(s, "read events: %ld\n", cnt);
5675 5678
5676 count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len); 5679 count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->seq.len);
5677 5680
5678 kfree(s); 5681 kfree(s);
5679 5682
@@ -6636,11 +6639,11 @@ void
6636trace_printk_seq(struct trace_seq *s) 6639trace_printk_seq(struct trace_seq *s)
6637{ 6640{
6638 /* Probably should print a warning here. */ 6641 /* Probably should print a warning here. */
6639 if (s->len >= TRACE_MAX_PRINT) 6642 if (s->seq.len >= TRACE_MAX_PRINT)
6640 s->len = TRACE_MAX_PRINT; 6643 s->seq.len = TRACE_MAX_PRINT;
6641 6644
6642 /* should be zero ended, but we are paranoid. */ 6645 /* should be zero ended, but we are paranoid. */
6643 s->buffer[s->len] = 0; 6646 s->buffer[s->seq.len] = 0;
6644 6647
6645 printk(KERN_TRACE "%s", s->buffer); 6648 printk(KERN_TRACE "%s", s->buffer);
6646 6649
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index f9d0cbe014b7..4d0067dd7f88 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1044,7 +1044,7 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
1044 mutex_unlock(&event_mutex); 1044 mutex_unlock(&event_mutex);
1045 1045
1046 if (file) 1046 if (file)
1047 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); 1047 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->seq.len);
1048 1048
1049 kfree(s); 1049 kfree(s);
1050 1050
@@ -1210,7 +1210,7 @@ subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
1210 trace_seq_init(s); 1210 trace_seq_init(s);
1211 1211
1212 print_subsystem_event_filter(system, s); 1212 print_subsystem_event_filter(system, s);
1213 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); 1213 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->seq.len);
1214 1214
1215 kfree(s); 1215 kfree(s);
1216 1216
@@ -1265,7 +1265,7 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1265 trace_seq_init(s); 1265 trace_seq_init(s);
1266 1266
1267 func(s); 1267 func(s);
1268 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); 1268 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->seq.len);
1269 1269
1270 kfree(s); 1270 kfree(s);
1271 1271
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 100288d10e1f..6d1342ae7a44 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -1154,9 +1154,9 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
1154 } 1154 }
1155 1155
1156 /* Strip ending newline */ 1156 /* Strip ending newline */
1157 if (s->buffer[s->len - 1] == '\n') { 1157 if (s->buffer[s->seq.len - 1] == '\n') {
1158 s->buffer[s->len - 1] = '\0'; 1158 s->buffer[s->seq.len - 1] = '\0';
1159 s->len--; 1159 s->seq.len--;
1160 } 1160 }
1161 1161
1162 trace_seq_puts(s, " */\n"); 1162 trace_seq_puts(s, " */\n");
diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c
index fabfa0f190a3..8c0c54fe674b 100644
--- a/kernel/trace/trace_seq.c
+++ b/kernel/trace/trace_seq.c
@@ -27,10 +27,19 @@
27#include <linux/trace_seq.h> 27#include <linux/trace_seq.h>
28 28
29/* How much buffer is left on the trace_seq? */ 29/* How much buffer is left on the trace_seq? */
30#define TRACE_SEQ_BUF_LEFT(s) ((PAGE_SIZE - 1) - (s)->len) 30#define TRACE_SEQ_BUF_LEFT(s) seq_buf_buffer_left(&(s)->seq)
31 31
32/* How much buffer is written? */ 32/* How much buffer is written? */
33#define TRACE_SEQ_BUF_USED(s) min((s)->len, (unsigned int)(PAGE_SIZE - 1)) 33#define TRACE_SEQ_BUF_USED(s) min((s)->seq.len, (unsigned int)(PAGE_SIZE - 1))
34
35/*
36 * trace_seq should work with being initialized with 0s.
37 */
38static inline void __trace_seq_init(struct trace_seq *s)
39{
40 if (unlikely(!s->seq.size))
41 trace_seq_init(s);
42}
34 43
35/** 44/**
36 * trace_print_seq - move the contents of trace_seq into a seq_file 45 * trace_print_seq - move the contents of trace_seq into a seq_file
@@ -43,10 +52,11 @@
43 */ 52 */
44int trace_print_seq(struct seq_file *m, struct trace_seq *s) 53int trace_print_seq(struct seq_file *m, struct trace_seq *s)
45{ 54{
46 unsigned int len = TRACE_SEQ_BUF_USED(s);
47 int ret; 55 int ret;
48 56
49 ret = seq_write(m, s->buffer, len); 57 __trace_seq_init(s);
58
59 ret = seq_buf_print_seq(m, &s->seq);
50 60
51 /* 61 /*
52 * Only reset this buffer if we successfully wrote to the 62 * Only reset this buffer if we successfully wrote to the
@@ -72,24 +82,23 @@ int trace_print_seq(struct seq_file *m, struct trace_seq *s)
72 */ 82 */
73void trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 83void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
74{ 84{
75 unsigned int len = TRACE_SEQ_BUF_LEFT(s); 85 unsigned int save_len = s->seq.len;
76 va_list ap; 86 va_list ap;
77 int ret;
78 87
79 if (s->full || !len) 88 if (s->full)
80 return; 89 return;
81 90
91 __trace_seq_init(s);
92
82 va_start(ap, fmt); 93 va_start(ap, fmt);
83 ret = vsnprintf(s->buffer + s->len, len, fmt, ap); 94 seq_buf_vprintf(&s->seq, fmt, ap);
84 va_end(ap); 95 va_end(ap);
85 96
86 /* If we can't write it all, don't bother writing anything */ 97 /* If we can't write it all, don't bother writing anything */
87 if (ret >= len) { 98 if (unlikely(seq_buf_has_overflowed(&s->seq))) {
99 s->seq.len = save_len;
88 s->full = 1; 100 s->full = 1;
89 return;
90 } 101 }
91
92 s->len += ret;
93} 102}
94EXPORT_SYMBOL_GPL(trace_seq_printf); 103EXPORT_SYMBOL_GPL(trace_seq_printf);
95 104
@@ -104,14 +113,19 @@ EXPORT_SYMBOL_GPL(trace_seq_printf);
104void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp, 113void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
105 int nmaskbits) 114 int nmaskbits)
106{ 115{
107 unsigned int len = TRACE_SEQ_BUF_LEFT(s); 116 unsigned int save_len = s->seq.len;
108 int ret;
109 117
110 if (s->full || !len) 118 if (s->full)
111 return; 119 return;
112 120
113 ret = bitmap_scnprintf(s->buffer + s->len, len, maskp, nmaskbits); 121 __trace_seq_init(s);
114 s->len += ret; 122
123 seq_buf_bitmask(&s->seq, maskp, nmaskbits);
124
125 if (unlikely(seq_buf_has_overflowed(&s->seq))) {
126 s->seq.len = save_len;
127 s->full = 1;
128 }
115} 129}
116EXPORT_SYMBOL_GPL(trace_seq_bitmask); 130EXPORT_SYMBOL_GPL(trace_seq_bitmask);
117 131
@@ -128,21 +142,20 @@ EXPORT_SYMBOL_GPL(trace_seq_bitmask);
128 */ 142 */
129void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) 143void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
130{ 144{
131 unsigned int len = TRACE_SEQ_BUF_LEFT(s); 145 unsigned int save_len = s->seq.len;
132 int ret;
133 146
134 if (s->full || !len) 147 if (s->full)
135 return; 148 return;
136 149
137 ret = vsnprintf(s->buffer + s->len, len, fmt, args); 150 __trace_seq_init(s);
151
152 seq_buf_vprintf(&s->seq, fmt, args);
138 153
139 /* If we can't write it all, don't bother writing anything */ 154 /* If we can't write it all, don't bother writing anything */
140 if (ret >= len) { 155 if (unlikely(seq_buf_has_overflowed(&s->seq))) {
156 s->seq.len = save_len;
141 s->full = 1; 157 s->full = 1;
142 return;
143 } 158 }
144
145 s->len += ret;
146} 159}
147EXPORT_SYMBOL_GPL(trace_seq_vprintf); 160EXPORT_SYMBOL_GPL(trace_seq_vprintf);
148 161
@@ -163,21 +176,21 @@ EXPORT_SYMBOL_GPL(trace_seq_vprintf);
163 */ 176 */
164void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) 177void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
165{ 178{
166 unsigned int len = TRACE_SEQ_BUF_LEFT(s); 179 unsigned int save_len = s->seq.len;
167 int ret;
168 180
169 if (s->full || !len) 181 if (s->full)
170 return; 182 return;
171 183
172 ret = bstr_printf(s->buffer + s->len, len, fmt, binary); 184 __trace_seq_init(s);
185
186 seq_buf_bprintf(&s->seq, fmt, binary);
173 187
174 /* If we can't write it all, don't bother writing anything */ 188 /* If we can't write it all, don't bother writing anything */
175 if (ret >= len) { 189 if (unlikely(seq_buf_has_overflowed(&s->seq))) {
190 s->seq.len = save_len;
176 s->full = 1; 191 s->full = 1;
177 return; 192 return;
178 } 193 }
179
180 s->len += ret;
181} 194}
182EXPORT_SYMBOL_GPL(trace_seq_bprintf); 195EXPORT_SYMBOL_GPL(trace_seq_bprintf);
183 196
@@ -198,13 +211,14 @@ void trace_seq_puts(struct trace_seq *s, const char *str)
198 if (s->full) 211 if (s->full)
199 return; 212 return;
200 213
214 __trace_seq_init(s);
215
201 if (len > TRACE_SEQ_BUF_LEFT(s)) { 216 if (len > TRACE_SEQ_BUF_LEFT(s)) {
202 s->full = 1; 217 s->full = 1;
203 return; 218 return;
204 } 219 }
205 220
206 memcpy(s->buffer + s->len, str, len); 221 seq_buf_putmem(&s->seq, str, len);
207 s->len += len;
208} 222}
209EXPORT_SYMBOL_GPL(trace_seq_puts); 223EXPORT_SYMBOL_GPL(trace_seq_puts);
210 224
@@ -223,12 +237,14 @@ void trace_seq_putc(struct trace_seq *s, unsigned char c)
223 if (s->full) 237 if (s->full)
224 return; 238 return;
225 239
240 __trace_seq_init(s);
241
226 if (TRACE_SEQ_BUF_LEFT(s) < 1) { 242 if (TRACE_SEQ_BUF_LEFT(s) < 1) {
227 s->full = 1; 243 s->full = 1;
228 return; 244 return;
229 } 245 }
230 246
231 s->buffer[s->len++] = c; 247 seq_buf_putc(&s->seq, c);
232} 248}
233EXPORT_SYMBOL_GPL(trace_seq_putc); 249EXPORT_SYMBOL_GPL(trace_seq_putc);
234 250
@@ -247,19 +263,17 @@ void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
247 if (s->full) 263 if (s->full)
248 return; 264 return;
249 265
266 __trace_seq_init(s);
267
250 if (len > TRACE_SEQ_BUF_LEFT(s)) { 268 if (len > TRACE_SEQ_BUF_LEFT(s)) {
251 s->full = 1; 269 s->full = 1;
252 return; 270 return;
253 } 271 }
254 272
255 memcpy(s->buffer + s->len, mem, len); 273 seq_buf_putmem(&s->seq, mem, len);
256 s->len += len;
257} 274}
258EXPORT_SYMBOL_GPL(trace_seq_putmem); 275EXPORT_SYMBOL_GPL(trace_seq_putmem);
259 276
260#define MAX_MEMHEX_BYTES 8U
261#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)
262
263/** 277/**
264 * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex 278 * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
265 * @s: trace sequence descriptor 279 * @s: trace sequence descriptor
@@ -273,32 +287,26 @@ EXPORT_SYMBOL_GPL(trace_seq_putmem);
273void trace_seq_putmem_hex(struct trace_seq *s, const void *mem, 287void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
274 unsigned int len) 288 unsigned int len)
275{ 289{
276 unsigned char hex[HEX_CHARS]; 290 unsigned int save_len = s->seq.len;
277 const unsigned char *data = mem;
278 unsigned int start_len;
279 int i, j;
280 291
281 if (s->full) 292 if (s->full)
282 return; 293 return;
283 294
284 while (len) { 295 __trace_seq_init(s);
285 start_len = min(len, HEX_CHARS - 1); 296
286#ifdef __BIG_ENDIAN 297 /* Each byte is represented by two chars */
287 for (i = 0, j = 0; i < start_len; i++) { 298 if (len * 2 > TRACE_SEQ_BUF_LEFT(s)) {
288#else 299 s->full = 1;
289 for (i = start_len-1, j = 0; i >= 0; i--) { 300 return;
290#endif 301 }
291 hex[j++] = hex_asc_hi(data[i]); 302
292 hex[j++] = hex_asc_lo(data[i]); 303 /* The added spaces can still cause an overflow */
293 } 304 seq_buf_putmem_hex(&s->seq, mem, len);
294 if (WARN_ON_ONCE(j == 0 || j/2 > len)) 305
295 break; 306 if (unlikely(seq_buf_has_overflowed(&s->seq))) {
296 307 s->seq.len = save_len;
297 /* j increments twice per loop */ 308 s->full = 1;
298 len -= j / 2; 309 return;
299 hex[j++] = ' ';
300
301 trace_seq_putmem(s, hex, j);
302 } 310 }
303} 311}
304EXPORT_SYMBOL_GPL(trace_seq_putmem_hex); 312EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
@@ -317,30 +325,28 @@ EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
317 */ 325 */
318int trace_seq_path(struct trace_seq *s, const struct path *path) 326int trace_seq_path(struct trace_seq *s, const struct path *path)
319{ 327{
320 unsigned char *p; 328 unsigned int save_len = s->seq.len;
329 int ret;
321 330
322 if (s->full) 331 if (s->full)
323 return 0; 332 return 0;
324 333
334 __trace_seq_init(s);
335
325 if (TRACE_SEQ_BUF_LEFT(s) < 1) { 336 if (TRACE_SEQ_BUF_LEFT(s) < 1) {
326 s->full = 1; 337 s->full = 1;
327 return 0; 338 return 0;
328 } 339 }
329 340
330 p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len); 341 ret = seq_buf_path(&s->seq, path);
331 if (!IS_ERR(p)) { 342
332 p = mangle_path(s->buffer + s->len, p, "\n"); 343 if (unlikely(seq_buf_has_overflowed(&s->seq))) {
333 if (p) { 344 s->seq.len = save_len;
334 s->len = p - s->buffer; 345 s->full = 1;
335 return 1; 346 return 0;
336 }
337 } else {
338 s->buffer[s->len++] = '?';
339 return 1;
340 } 347 }
341 348
342 s->full = 1; 349 return ret;
343 return 0;
344} 350}
345EXPORT_SYMBOL_GPL(trace_seq_path); 351EXPORT_SYMBOL_GPL(trace_seq_path);
346 352
@@ -366,25 +372,7 @@ EXPORT_SYMBOL_GPL(trace_seq_path);
366 */ 372 */
367int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt) 373int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
368{ 374{
369 int len; 375 __trace_seq_init(s);
370 int ret; 376 return seq_buf_to_user(&s->seq, ubuf, cnt);
371
372 if (!cnt)
373 return 0;
374
375 if (s->len <= s->readpos)
376 return -EBUSY;
377
378 len = s->len - s->readpos;
379 if (cnt > len)
380 cnt = len;
381 ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
382 if (ret == cnt)
383 return -EFAULT;
384
385 cnt -= ret;
386
387 s->readpos += cnt;
388 return cnt;
389} 377}
390EXPORT_SYMBOL_GPL(trace_seq_to_user); 378EXPORT_SYMBOL_GPL(trace_seq_to_user);