tracing: Add full state to trace_seq
authorJohannes Berg <johannes@sipsolutions.net>
Wed, 25 Nov 2009 15:10:14 +0000 (16:10 +0100)
committerSteven Rostedt <rostedt@goodmis.org>
Wed, 9 Dec 2009 19:05:49 +0000 (14:05 -0500)
The trace_seq buffer might fill up, and right now one needs to check the
return value of each printf into the buffer to check for that.

Instead, have the buffer keep track of whether it is full or not, and
reject more input if it is full or would have overflowed with an input
that wasn't added.

Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
include/linux/trace_seq.h
kernel/trace/trace_output.c

index fad6857bc0f3b0e0a8ee78a984f774d76dd71752..5cf397ceb726fee2c48da416f8ade27c1ae6a7f5 100644 (file)
@@ -14,6 +14,7 @@ struct trace_seq {
        unsigned char           buffer[PAGE_SIZE];
        unsigned int            len;
        unsigned int            readpos;
+       int                     full;
 };
 
 static inline void
@@ -21,6 +22,7 @@ trace_seq_init(struct trace_seq *s)
 {
        s->len = 0;
        s->readpos = 0;
+       s->full = 0;
 }
 
 /*
index e5cf90fef34e928546b962a2afa5927e0f5964d4..8e46b3323cdcdd91ad9833aa1eb8d0f1bf82f3af 100644 (file)
@@ -93,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);
@@ -101,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;
 
@@ -127,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;
 
@@ -147,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;
 
@@ -175,9 +181,14 @@ 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;
 
@@ -186,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;
@@ -196,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;
 
@@ -211,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
@@ -228,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 0;
+
+       if (len > ((PAGE_SIZE - 1) - s->len)) {
+               s->full = 1;
                return NULL;
+       }
 
        ret = s->buffer + s->len;
        s->len += len;
@@ -241,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");
@@ -255,6 +290,7 @@ int trace_seq_path(struct trace_seq *s, struct path *path)
                return 1;
        }
 
+       s->full = 1;
        return 0;
 }
 
@@ -381,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;