trace: judicious error checking of trace_seq results
[safe/jmp/linux-2.6] / kernel / trace / trace_output.c
index df0c25c..5b3c914 100644 (file)
@@ -286,6 +286,92 @@ seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
        return ret;
 }
 
+static int
+lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
+{
+       int hardirq, softirq;
+       char *comm;
+
+       comm = trace_find_cmdline(entry->pid);
+       hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
+       softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
+
+       if (!trace_seq_printf(s, "%8.8s-%-5d %3d%c%c%c",
+                             comm, entry->pid, cpu,
+                             (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
+                               (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
+                                 'X' : '.',
+                             (entry->flags & TRACE_FLAG_NEED_RESCHED) ?
+                               'N' : '.',
+                             (hardirq && softirq) ? 'H' :
+                               hardirq ? 'h' : softirq ? 's' : '.'))
+               return 0;
+
+       if (entry->preempt_count)
+               return trace_seq_printf(s, "%x", entry->preempt_count);
+       return trace_seq_puts(s, ".");
+}
+
+static unsigned long preempt_mark_thresh = 100;
+
+static int
+lat_print_timestamp(struct trace_seq *s, u64 abs_usecs,
+                   unsigned long rel_usecs)
+{
+       return trace_seq_printf(s, " %4lldus%c: ", abs_usecs,
+                               rel_usecs > preempt_mark_thresh ? '!' :
+                                 rel_usecs > 1 ? '+' : ' ');
+}
+
+int trace_print_context(struct trace_iterator *iter)
+{
+       struct trace_seq *s = &iter->seq;
+       struct trace_entry *entry = iter->ent;
+       char *comm = trace_find_cmdline(entry->pid);
+       unsigned long long t = ns2usecs(iter->ts);
+       unsigned long usec_rem = do_div(t, USEC_PER_SEC);
+       unsigned long secs = (unsigned long)t;
+
+       return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ",
+                               comm, entry->pid, entry->cpu, secs, usec_rem);
+}
+
+int trace_print_lat_context(struct trace_iterator *iter)
+{
+       u64 next_ts;
+       int ret;
+       struct trace_seq *s = &iter->seq;
+       struct trace_entry *entry = iter->ent,
+                          *next_entry = trace_find_next_entry(iter, NULL,
+                                                              &next_ts);
+       unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
+       unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start);
+       unsigned long rel_usecs;
+
+       if (!next_entry)
+               next_ts = iter->ts;
+       rel_usecs = ns2usecs(next_ts - iter->ts);
+
+       if (verbose) {
+               char *comm = trace_find_cmdline(entry->pid);
+               ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08lx]"
+                                      " %ld.%03ldms (+%ld.%03ldms): ", comm,
+                                      entry->pid, entry->cpu, entry->flags,
+                                      entry->preempt_count, iter->idx,
+                                      ns2usecs(iter->ts),
+                                      abs_usecs / USEC_PER_MSEC,
+                                      abs_usecs % USEC_PER_MSEC,
+                                      rel_usecs / USEC_PER_MSEC,
+                                      rel_usecs % USEC_PER_MSEC);
+       } else {
+               ret = lat_print_generic(s, entry, entry->cpu);
+               if (ret)
+                       ret = lat_print_timestamp(s, abs_usecs, rel_usecs);
+       }
+
+       return ret;
+}
+
 static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
 
 static int task_state_char(unsigned long state)
@@ -377,19 +463,18 @@ int unregister_ftrace_event(struct trace_event *event)
  * Standard events
  */
 
-int
-trace_nop_print(struct trace_seq *s, struct trace_entry *entry, int flags)
+int trace_nop_print(struct trace_iterator *iter, int flags)
 {
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
 /* TRACE_FN */
-static int
-trace_fn_latency(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_fn_latency(struct trace_iterator *iter, int flags)
 {
        struct ftrace_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        if (!seq_print_ip_sym(s, field->ip, flags))
                goto partial;
@@ -400,18 +485,18 @@ trace_fn_latency(struct trace_seq *s, struct trace_entry *entry, int flags)
        if (!trace_seq_puts(s, ")\n"))
                goto partial;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 
  partial:
        return TRACE_TYPE_PARTIAL_LINE;
 }
 
-static int
-trace_fn_trace(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_fn_trace(struct trace_iterator *iter, int flags)
 {
        struct ftrace_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        if (!seq_print_ip_sym(s, field->ip, flags))
                goto partial;
@@ -427,51 +512,50 @@ trace_fn_trace(struct trace_seq *s, struct trace_entry *entry, int flags)
        if (!trace_seq_printf(s, "\n"))
                goto partial;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 
  partial:
        return TRACE_TYPE_PARTIAL_LINE;
 }
 
-static int
-trace_fn_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_fn_raw(struct trace_iterator *iter, int flags)
 {
        struct ftrace_entry *field;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
-       if (trace_seq_printf(s, "%x %x\n",
-                            field->ip,
-                            field->parent_ip))
+       if (!trace_seq_printf(&iter->seq, "%lx %lx\n",
+                             field->ip,
+                             field->parent_ip))
                return TRACE_TYPE_PARTIAL_LINE;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
-static int
-trace_fn_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_fn_hex(struct trace_iterator *iter, int flags)
 {
        struct ftrace_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        SEQ_PUT_HEX_FIELD_RET(s, field->ip);
        SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
-static int
-trace_fn_bin(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_fn_bin(struct trace_iterator *iter, int flags)
 {
        struct ftrace_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        SEQ_PUT_FIELD_RET(s, field->ip);
        SEQ_PUT_FIELD_RET(s, field->parent_ip);
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
 static struct trace_event trace_fn_event = {
@@ -484,90 +568,82 @@ static struct trace_event trace_fn_event = {
 };
 
 /* TRACE_CTX an TRACE_WAKE */
-static int
-trace_ctxwake_print(struct trace_seq *s, struct trace_entry *entry, int flags,
-                   char *delim)
+static int trace_ctxwake_print(struct trace_iterator *iter, char *delim)
 {
        struct ctx_switch_entry *field;
        char *comm;
        int S, T;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        T = task_state_char(field->next_state);
        S = task_state_char(field->prev_state);
        comm = trace_find_cmdline(field->next_pid);
-       if (trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
-                            field->prev_pid,
-                            field->prev_prio,
-                            S, delim,
-                            field->next_cpu,
-                            field->next_pid,
-                            field->next_prio,
-                            T, comm))
+       if (!trace_seq_printf(&iter->seq,
+                             " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
+                             field->prev_pid,
+                             field->prev_prio,
+                             S, delim,
+                             field->next_cpu,
+                             field->next_pid,
+                             field->next_prio,
+                             T, comm))
                return TRACE_TYPE_PARTIAL_LINE;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
-static int
-trace_ctx_print(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_ctx_print(struct trace_iterator *iter, int flags)
 {
-       return trace_ctxwake_print(s, entry, flags, "==>");
+       return trace_ctxwake_print(iter, "==>");
 }
 
-static int
-trace_wake_print(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_wake_print(struct trace_iterator *iter, int flags)
 {
-       return trace_ctxwake_print(s, entry, flags, "  +");
+       return trace_ctxwake_print(iter, "  +");
 }
 
-static int
-trace_ctxwake_raw(struct trace_seq *s, struct trace_entry *entry, int flags,
-                 char S)
+static int trace_ctxwake_raw(struct trace_iterator *iter, char S)
 {
        struct ctx_switch_entry *field;
        int T;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        if (!S)
                task_state_char(field->prev_state);
        T = task_state_char(field->next_state);
-       if (trace_seq_printf(s, "%d %d %c %d %d %d %c\n",
-                            field->prev_pid,
-                            field->prev_prio,
-                            S,
-                            field->next_cpu,
-                            field->next_pid,
-                            field->next_prio,
-                            T))
+       if (!trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
+                             field->prev_pid,
+                             field->prev_prio,
+                             S,
+                             field->next_cpu,
+                             field->next_pid,
+                             field->next_prio,
+                             T))
                return TRACE_TYPE_PARTIAL_LINE;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
-static int
-trace_ctx_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_ctx_raw(struct trace_iterator *iter, int flags)
 {
-       return trace_ctxwake_raw(s, entry, flags, 0);
+       return trace_ctxwake_raw(iter, 0);
 }
 
-static int
-trace_wake_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_wake_raw(struct trace_iterator *iter, int flags)
 {
-       return trace_ctxwake_raw(s, entry, flags, '+');
+       return trace_ctxwake_raw(iter, '+');
 }
 
 
-static int
-trace_ctxwake_hex(struct trace_seq *s, struct trace_entry *entry, int flags,
-                 char S)
+static int trace_ctxwake_hex(struct trace_iterator *iter, char S)
 {
        struct ctx_switch_entry *field;
+       struct trace_seq *s = &iter->seq;
        int T;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        if (!S)
                task_state_char(field->prev_state);
@@ -581,27 +657,25 @@ trace_ctxwake_hex(struct trace_seq *s, struct trace_entry *entry, int flags,
        SEQ_PUT_HEX_FIELD_RET(s, field->next_prio);
        SEQ_PUT_HEX_FIELD_RET(s, T);
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
-static int
-trace_ctx_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_ctx_hex(struct trace_iterator *iter, int flags)
 {
-       return trace_ctxwake_hex(s, entry, flags, 0);
+       return trace_ctxwake_hex(iter, 0);
 }
 
-static int
-trace_wake_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_wake_hex(struct trace_iterator *iter, int flags)
 {
-       return trace_ctxwake_hex(s, entry, flags, '+');
+       return trace_ctxwake_hex(iter, '+');
 }
 
-static int
-trace_ctxwake_bin(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_ctxwake_bin(struct trace_iterator *iter, int flags)
 {
        struct ctx_switch_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        SEQ_PUT_FIELD_RET(s, field->prev_pid);
        SEQ_PUT_FIELD_RET(s, field->prev_prio);
@@ -610,7 +684,7 @@ trace_ctxwake_bin(struct trace_seq *s, struct trace_entry *entry, int flags)
        SEQ_PUT_FIELD_RET(s, field->next_prio);
        SEQ_PUT_FIELD_RET(s, field->next_state);
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
 static struct trace_event trace_ctx_event = {
@@ -632,48 +706,47 @@ static struct trace_event trace_wake_event = {
 };
 
 /* TRACE_SPECIAL */
-static int
-trace_special_print(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_special_print(struct trace_iterator *iter, int flags)
 {
        struct special_entry *field;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
-       if (trace_seq_printf(s, "# %ld %ld %ld\n",
-                            field->arg1,
-                            field->arg2,
-                            field->arg3))
+       if (!trace_seq_printf(&iter->seq, "# %ld %ld %ld\n",
+                             field->arg1,
+                             field->arg2,
+                             field->arg3))
                return TRACE_TYPE_PARTIAL_LINE;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
-static int
-trace_special_hex(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_special_hex(struct trace_iterator *iter, int flags)
 {
        struct special_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
        SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
        SEQ_PUT_HEX_FIELD_RET(s, field->arg3);
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
-static int
-trace_special_bin(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_special_bin(struct trace_iterator *iter, int flags)
 {
        struct special_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        SEQ_PUT_FIELD_RET(s, field->arg1);
        SEQ_PUT_FIELD_RET(s, field->arg2);
        SEQ_PUT_FIELD_RET(s, field->arg3);
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 }
 
 static struct trace_event trace_special_event = {
@@ -687,27 +760,27 @@ static struct trace_event trace_special_event = {
 
 /* TRACE_STACK */
 
-static int
-trace_stack_print(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_stack_print(struct trace_iterator *iter, int flags)
 {
        struct stack_entry *field;
+       struct trace_seq *s = &iter->seq;
        int i;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
        for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
                if (i) {
-                       if (trace_seq_puts(s, " <= "))
+                       if (!trace_seq_puts(s, " <= "))
                                goto partial;
 
-                       if (seq_print_ip_sym(s, field->caller[i], flags))
+                       if (!seq_print_ip_sym(s, field->caller[i], flags))
                                goto partial;
                }
-               if (trace_seq_puts(s, "\n"))
+               if (!trace_seq_puts(s, "\n"))
                        goto partial;
        }
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 
  partial:
        return TRACE_TYPE_PARTIAL_LINE;
@@ -723,21 +796,20 @@ static struct trace_event trace_stack_event = {
 };
 
 /* TRACE_USER_STACK */
-static int
-trace_user_stack_print(struct trace_seq *s, struct trace_entry *entry,
-                      int flags)
+static int trace_user_stack_print(struct trace_iterator *iter, int flags)
 {
        struct userstack_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
-       if (seq_print_userip_objs(field, s, flags))
+       if (!seq_print_userip_objs(field, s, flags))
                goto partial;
 
-       if (trace_seq_putc(s, '\n'))
+       if (!trace_seq_putc(s, '\n'))
                goto partial;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 
  partial:
        return TRACE_TYPE_PARTIAL_LINE;
@@ -753,39 +825,35 @@ static struct trace_event trace_user_stack_event = {
 };
 
 /* TRACE_PRINT */
-static int
-trace_print_print(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_print_print(struct trace_iterator *iter, int flags)
 {
        struct print_entry *field;
+       struct trace_seq *s = &iter->seq;
 
-       trace_assign_type(field, entry);
+       trace_assign_type(field, iter->ent);
 
-       if (seq_print_ip_sym(s, field->ip, flags))
+       if (!seq_print_ip_sym(s, field->ip, flags))
                goto partial;
 
-       if (trace_seq_printf(s, ": %s", field->buf))
+       if (!trace_seq_printf(s, ": %s", field->buf))
                goto partial;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 
  partial:
        return TRACE_TYPE_PARTIAL_LINE;
 }
 
-static int
-trace_print_raw(struct trace_seq *s, struct trace_entry *entry, int flags)
+static int trace_print_raw(struct trace_iterator *iter, int flags)
 {
        struct print_entry *field;
 
-       trace_assign_type(field, entry);
-
-       if (seq_print_ip_sym(s, field->ip, flags))
-               goto partial;
+       trace_assign_type(field, iter->ent);
 
-       if (trace_seq_printf(s, "# %lx %s", field->ip, field->buf))
+       if (!trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf))
                goto partial;
 
-       return 0;
+       return TRACE_TYPE_HANDLED;
 
  partial:
        return TRACE_TYPE_PARTIAL_LINE;