Skip to content

Commit b91facc

Browse files
fweisbecIngo Molnar
authored andcommitted
tracing/function-graph-tracer: handle the leaf functions from trace_pipe
When one cats the trace file, the leaf functions are printed without brackets: function(); whereas in the trace_pipe file we'll see the following: function() { } This is because the ring_buffer handling is not the same between those two files. On the trace file, when an entry is printed, the iterator advanced and then we can check the next entry. There is no iterator with trace_pipe, the current entry to print has been peeked and not consumed. So checking the next entry will still return the current one while we don't consume it. This patch introduces a new value for the output callbacks to ask the tracing core to not consume the current entry after printing it. We need it because we will have to consume the current entry ourself to check the next one. Now the trace_pipe is able to handle well the leaf functions. Signed-off-by: Frederic Weisbecker <[email protected]> Acked-by: Steven Rostedt <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 1dfba05 commit b91facc

File tree

3 files changed

+36
-23
lines changed

3 files changed

+36
-23
lines changed

kernel/trace/trace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,8 +2468,8 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
24682468
iter->seq.len = len;
24692469
break;
24702470
}
2471-
2472-
trace_consume(iter);
2471+
if (ret != TRACE_TYPE_NO_CONSUME)
2472+
trace_consume(iter);
24732473

24742474
if (iter->seq.len >= cnt)
24752475
break;

kernel/trace/trace.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ struct ftrace_entry {
6363

6464
/* Function call entry */
6565
struct ftrace_graph_ent_entry {
66-
struct trace_entry ent;
66+
struct trace_entry ent;
6767
struct ftrace_graph_ent graph_ent;
6868
};
6969

7070
/* Function return entry */
7171
struct ftrace_graph_ret_entry {
72-
struct trace_entry ent;
72+
struct trace_entry ent;
7373
struct ftrace_graph_ret ret;
7474
};
7575
extern struct tracer boot_tracer;
@@ -309,7 +309,8 @@ extern void __ftrace_bad_type(void);
309309
enum print_line_t {
310310
TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */
311311
TRACE_TYPE_HANDLED = 1,
312-
TRACE_TYPE_UNHANDLED = 2 /* Relay to other output functions */
312+
TRACE_TYPE_UNHANDLED = 2, /* Relay to other output functions */
313+
TRACE_TYPE_NO_CONSUME = 3 /* Handled but ask to not consume */
313314
};
314315

315316

kernel/trace/trace_functions_graph.c

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ verif_pid(struct trace_seq *s, pid_t pid, int cpu, pid_t *last_pids_cpu)
212212
return ret;
213213
}
214214

215-
static bool
216-
trace_branch_is_leaf(struct trace_iterator *iter,
215+
static struct ftrace_graph_ret_entry *
216+
get_return_for_leaf(struct trace_iterator *iter,
217217
struct ftrace_graph_ent_entry *curr)
218218
{
219219
struct ring_buffer_iter *ring_iter;
@@ -222,24 +222,33 @@ trace_branch_is_leaf(struct trace_iterator *iter,
222222

223223
ring_iter = iter->buffer_iter[iter->cpu];
224224

225-
if (!ring_iter)
226-
return false;
227-
228-
event = ring_buffer_iter_peek(ring_iter, NULL);
225+
/* First peek to compare current entry and the next one */
226+
if (ring_iter)
227+
event = ring_buffer_iter_peek(ring_iter, NULL);
228+
else {
229+
/* We need to consume the current entry to see the next one */
230+
ring_buffer_consume(iter->tr->buffer, iter->cpu, NULL);
231+
event = ring_buffer_peek(iter->tr->buffer, iter->cpu,
232+
NULL);
233+
}
229234

230235
if (!event)
231-
return false;
236+
return NULL;
232237

233238
next = ring_buffer_event_data(event);
234239

235240
if (next->ent.type != TRACE_GRAPH_RET)
236-
return false;
241+
return NULL;
237242

238243
if (curr->ent.pid != next->ent.pid ||
239244
curr->graph_ent.func != next->ret.func)
240-
return false;
245+
return NULL;
241246

242-
return true;
247+
/* this is a leaf, now advance the iterator */
248+
if (ring_iter)
249+
ring_buffer_read(ring_iter, NULL);
250+
251+
return next;
243252
}
244253

245254
/* Signal a overhead of time execution to the output */
@@ -376,18 +385,15 @@ static int print_graph_abs_time(u64 t, struct trace_seq *s)
376385
/* Case of a leaf function on its call entry */
377386
static enum print_line_t
378387
print_graph_entry_leaf(struct trace_iterator *iter,
379-
struct ftrace_graph_ent_entry *entry, struct trace_seq *s)
388+
struct ftrace_graph_ent_entry *entry,
389+
struct ftrace_graph_ret_entry *ret_entry, struct trace_seq *s)
380390
{
381-
struct ftrace_graph_ret_entry *ret_entry;
382391
struct ftrace_graph_ret *graph_ret;
383-
struct ring_buffer_event *event;
384392
struct ftrace_graph_ent *call;
385393
unsigned long long duration;
386394
int ret;
387395
int i;
388396

389-
event = ring_buffer_read(iter->buffer_iter[iter->cpu], NULL);
390-
ret_entry = ring_buffer_event_data(event);
391397
graph_ret = &ret_entry->ret;
392398
call = &entry->graph_ent;
393399
duration = graph_ret->rettime - graph_ret->calltime;
@@ -457,7 +463,11 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry,
457463
if (!ret)
458464
return TRACE_TYPE_PARTIAL_LINE;
459465

460-
return TRACE_TYPE_HANDLED;
466+
/*
467+
* we already consumed the current entry to check the next one
468+
* and see if this is a leaf.
469+
*/
470+
return TRACE_TYPE_NO_CONSUME;
461471
}
462472

463473
static enum print_line_t
@@ -469,6 +479,7 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
469479
pid_t *last_entry = iter->private;
470480
struct trace_entry *ent = iter->ent;
471481
struct ftrace_graph_ent *call = &field->graph_ent;
482+
struct ftrace_graph_ret_entry *leaf_ret;
472483

473484
/* Pid */
474485
if (verif_pid(s, ent->pid, cpu, last_entry) == TRACE_TYPE_PARTIAL_LINE)
@@ -504,8 +515,9 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
504515
return TRACE_TYPE_PARTIAL_LINE;
505516
}
506517

507-
if (trace_branch_is_leaf(iter, field))
508-
return print_graph_entry_leaf(iter, field, s);
518+
leaf_ret = get_return_for_leaf(iter, field);
519+
if (leaf_ret)
520+
return print_graph_entry_leaf(iter, field, leaf_ret, s);
509521
else
510522
return print_graph_entry_nested(field, s, iter->ent->pid, cpu);
511523

0 commit comments

Comments
 (0)