diff options
-rw-r--r-- | include/linux/ftrace_event.h | 1 | ||||
-rw-r--r-- | include/linux/trace_seq.h | 5 | ||||
-rw-r--r-- | kernel/trace/trace.c | 35 | ||||
-rw-r--r-- | kernel/trace/trace_output.c | 14 |
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))); |
34 | extern int | 34 | extern int |
35 | trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); | 35 | trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary); |
36 | extern void trace_print_seq(struct seq_file *m, struct trace_seq *s); | 36 | extern int trace_print_seq(struct seq_file *m, struct trace_seq *s); |
37 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, | 37 | extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, |
38 | size_t cnt); | 38 | size_t cnt); |
39 | extern int trace_seq_puts(struct trace_seq *s, const char *str); | 39 | extern 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 | ||
58 | static inline void trace_print_seq(struct seq_file *m, struct trace_seq *s) | 58 | static inline int trace_print_seq(struct seq_file *m, struct trace_seq *s) |
59 | { | 59 | { |
60 | return 0; | ||
60 | } | 61 | } |
61 | static inline ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, | 62 | static 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) | |||
1923 | static int s_show(struct seq_file *m, void *v) | 1933 | static 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 | ||
24 | static int next_event_type = __TRACE_LAST_TYPE + 1; | 24 | static int next_event_type = __TRACE_LAST_TYPE + 1; |
25 | 25 | ||
26 | void trace_print_seq(struct seq_file *m, struct trace_seq *s) | 26 | int 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 | ||
35 | enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) | 43 | enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) |