Merge branch 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[safe/jmp/linux-2.6] / kernel / trace / trace_output.c
index b6c12c6..2404c12 100644 (file)
@@ -23,13 +23,21 @@ static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
 
 static int next_event_type = __TRACE_LAST_TYPE + 1;
 
-void trace_print_seq(struct seq_file *m, struct trace_seq *s)
+int trace_print_seq(struct seq_file *m, struct trace_seq *s)
 {
        int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
+       int ret;
+
+       ret = seq_write(m, s->buffer, len);
 
-       seq_write(m, s->buffer, len);
+       /*
+        * Only reset this buffer if we successfully wrote to the
+        * seq_file buffer.
+        */
+       if (!ret)
+               trace_seq_init(s);
 
-       trace_seq_init(s);
+       return ret;
 }
 
 enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)
@@ -85,7 +93,7 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
        va_list ap;
        int ret;
 
-       if (!len)
+       if (s->full || !len)
                return 0;
 
        va_start(ap, fmt);
@@ -93,8 +101,10 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
        va_end(ap);
 
        /* If we can't write it all, don't bother writing anything */
-       if (ret >= len)
+       if (ret >= len) {
+               s->full = 1;
                return 0;
+       }
 
        s->len += ret;
 
@@ -119,14 +129,16 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
        int len = (PAGE_SIZE - 1) - s->len;
        int ret;
 
-       if (!len)
+       if (s->full || !len)
                return 0;
 
        ret = vsnprintf(s->buffer + s->len, len, fmt, args);
 
        /* If we can't write it all, don't bother writing anything */
-       if (ret >= len)
+       if (ret >= len) {
+               s->full = 1;
                return 0;
+       }
 
        s->len += ret;
 
@@ -139,14 +151,16 @@ int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
        int len = (PAGE_SIZE - 1) - s->len;
        int ret;
 
-       if (!len)
+       if (s->full || !len)
                return 0;
 
        ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
 
        /* If we can't write it all, don't bother writing anything */
-       if (ret >= len)
+       if (ret >= len) {
+               s->full = 1;
                return 0;
+       }
 
        s->len += ret;
 
@@ -167,8 +181,13 @@ int trace_seq_puts(struct trace_seq *s, const char *str)
 {
        int len = strlen(str);
 
-       if (len > ((PAGE_SIZE - 1) - s->len))
+       if (s->full)
+               return 0;
+
+       if (len > ((PAGE_SIZE - 1) - s->len)) {
+               s->full = 1;
                return 0;
+       }
 
        memcpy(s->buffer + s->len, str, len);
        s->len += len;
@@ -178,9 +197,14 @@ int trace_seq_puts(struct trace_seq *s, const char *str)
 
 int trace_seq_putc(struct trace_seq *s, unsigned char c)
 {
-       if (s->len >= (PAGE_SIZE - 1))
+       if (s->full)
                return 0;
 
+       if (s->len >= (PAGE_SIZE - 1)) {
+               s->full = 1;
+               return 0;
+       }
+
        s->buffer[s->len++] = c;
 
        return 1;
@@ -188,9 +212,14 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c)
 
 int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len)
 {
-       if (len > ((PAGE_SIZE - 1) - s->len))
+       if (s->full)
                return 0;
 
+       if (len > ((PAGE_SIZE - 1) - s->len)) {
+               s->full = 1;
+               return 0;
+       }
+
        memcpy(s->buffer + s->len, mem, len);
        s->len += len;
 
@@ -203,6 +232,9 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, size_t len)
        const unsigned char *data = mem;
        int i, j;
 
+       if (s->full)
+               return 0;
+
 #ifdef __BIG_ENDIAN
        for (i = 0, j = 0; i < len; i++) {
 #else
@@ -220,8 +252,13 @@ void *trace_seq_reserve(struct trace_seq *s, size_t len)
 {
        void *ret;
 
-       if (len > ((PAGE_SIZE - 1) - s->len))
+       if (s->full)
+               return NULL;
+
+       if (len > ((PAGE_SIZE - 1) - s->len)) {
+               s->full = 1;
                return NULL;
+       }
 
        ret = s->buffer + s->len;
        s->len += len;
@@ -233,8 +270,14 @@ int trace_seq_path(struct trace_seq *s, struct path *path)
 {
        unsigned char *p;
 
-       if (s->len >= (PAGE_SIZE - 1))
+       if (s->full)
+               return 0;
+
+       if (s->len >= (PAGE_SIZE - 1)) {
+               s->full = 1;
                return 0;
+       }
+
        p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
        if (!IS_ERR(p)) {
                p = mangle_path(s->buffer + s->len, p, "\n");
@@ -247,6 +290,7 @@ int trace_seq_path(struct trace_seq *s, struct path *path)
                return 1;
        }
 
+       s->full = 1;
        return 0;
 }
 
@@ -373,6 +417,9 @@ int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
        unsigned long vmstart = 0;
        int ret = 1;
 
+       if (s->full)
+               return 0;
+
        if (mm) {
                const struct vm_area_struct *vma;