aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace_event.h1
-rw-r--r--include/linux/trace_seq.h5
-rw-r--r--kernel/trace/trace.c35
-rw-r--r--kernel/trace/trace_output.c14
4 files changed, 47 insertions, 8 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 47bbdf9c38d0..38f8d6553831 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -57,6 +57,7 @@ struct trace_iterator {
57 /* The below is zeroed out in pipe_read */ 57 /* The below is zeroed out in pipe_read */
58 struct trace_seq seq; 58 struct trace_seq seq;
59 struct trace_entry *ent; 59 struct trace_entry *ent;
60 int leftover;
60 int cpu; 61 int cpu;
61 u64 ts; 62 u64 ts;
62 63
diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h
index 09077f6ed128..fad6857bc0f3 100644
--- a/include/linux/trace_seq.h
+++ b/include/linux/trace_seq.h
@@ -33,7 +33,7 @@ extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
33 __attribute__ ((format (printf, 2, 0))); 33 __attribute__ ((format (printf, 2, 0)));
34extern int 34extern int
35trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); 35trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
36extern void trace_print_seq(struct seq_file *m, struct trace_seq *s); 36extern int trace_print_seq(struct seq_file *m, struct trace_seq *s);
37extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, 37extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
38 size_t cnt); 38 size_t cnt);
39extern int trace_seq_puts(struct trace_seq *s, const char *str); 39extern int trace_seq_puts(struct trace_seq *s, const char *str);
@@ -55,8 +55,9 @@ trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
55 return 0; 55 return 0;
56} 56}
57 57
58static inline void trace_print_seq(struct seq_file *m, struct trace_seq *s) 58static inline int trace_print_seq(struct seq_file *m, struct trace_seq *s)
59{ 59{
60 return 0;
60} 61}
61static inline ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, 62static inline ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
62 size_t cnt) 63 size_t cnt)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index dc937e1baa91..484114d70743 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1516,6 +1516,8 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos)
1516 int i = (int)*pos; 1516 int i = (int)*pos;
1517 void *ent; 1517 void *ent;
1518 1518
1519 WARN_ON_ONCE(iter->leftover);
1520
1519 (*pos)++; 1521 (*pos)++;
1520 1522
1521 /* can't go backwards */ 1523 /* can't go backwards */
@@ -1614,8 +1616,16 @@ static void *s_start(struct seq_file *m, loff_t *pos)
1614 ; 1616 ;
1615 1617
1616 } else { 1618 } else {
1617 l = *pos - 1; 1619 /*
1618 p = s_next(m, p, &l); 1620 * If we overflowed the seq_file before, then we want
1621 * to just reuse the trace_seq buffer again.
1622 */
1623 if (iter->leftover)
1624 p = iter;
1625 else {
1626 l = *pos - 1;
1627 p = s_next(m, p, &l);
1628 }
1619 } 1629 }
1620 1630
1621 trace_event_read_lock(); 1631 trace_event_read_lock();
@@ -1923,6 +1933,7 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter)
1923static int s_show(struct seq_file *m, void *v) 1933static int s_show(struct seq_file *m, void *v)
1924{ 1934{
1925 struct trace_iterator *iter = v; 1935 struct trace_iterator *iter = v;
1936 int ret;
1926 1937
1927 if (iter->ent == NULL) { 1938 if (iter->ent == NULL) {
1928 if (iter->tr) { 1939 if (iter->tr) {
@@ -1942,9 +1953,27 @@ static int s_show(struct seq_file *m, void *v)
1942 if (!(trace_flags & TRACE_ITER_VERBOSE)) 1953 if (!(trace_flags & TRACE_ITER_VERBOSE))
1943 print_func_help_header(m); 1954 print_func_help_header(m);
1944 } 1955 }
1956 } else if (iter->leftover) {
1957 /*
1958 * If we filled the seq_file buffer earlier, we
1959 * want to just show it now.
1960 */
1961 ret = trace_print_seq(m, &iter->seq);
1962
1963 /* ret should this time be zero, but you never know */
1964 iter->leftover = ret;
1965
1945 } else { 1966 } else {
1946 print_trace_line(iter); 1967 print_trace_line(iter);
1947 trace_print_seq(m, &iter->seq); 1968 ret = trace_print_seq(m, &iter->seq);
1969 /*
1970 * If we overflow the seq_file buffer, then it will
1971 * ask us for this data again at start up.
1972 * Use that instead.
1973 * ret is 0 if seq_file write succeeded.
1974 * -1 otherwise.
1975 */
1976 iter->leftover = ret;
1948 } 1977 }
1949 1978
1950 return 0; 1979 return 0;
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index b6c12c6a1bcd..e5cf90fef34e 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -23,13 +23,21 @@ static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
23 23
24static int next_event_type = __TRACE_LAST_TYPE + 1; 24static int next_event_type = __TRACE_LAST_TYPE + 1;
25 25
26void trace_print_seq(struct seq_file *m, struct trace_seq *s) 26int trace_print_seq(struct seq_file *m, struct trace_seq *s)
27{ 27{
28 int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; 28 int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
29 int ret;
30
31 ret = seq_write(m, s->buffer, len);
29 32
30 seq_write(m, s->buffer, len); 33 /*
34 * Only reset this buffer if we successfully wrote to the
35 * seq_file buffer.
36 */
37 if (!ret)
38 trace_seq_init(s);
31 39
32 trace_seq_init(s); 40 return ret;
33} 41}
34 42
35enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) 43enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)