Skip to content
  • Steven Rostedt's avatar
    tracing: Buffer the output of seq_file in case of filled buffer · a63ce5b3
    Steven Rostedt authored
    
    
    If the seq_read fills the buffer it will call s_start again on the next
    itertation with the same position. This causes a problem with the
    function_graph tracer because it consumes the iteration in order to
    determine leaf functions.
    
    What happens is that the iterator stores the entry, and the function
    graph plugin will look at the next entry. If that next entry is a return
    of the same function and task, then the function is a leaf and the
    function_graph plugin calls ring_buffer_read which moves the ring buffer
    iterator forward (the trace iterator still points to the function start
    entry).
    
    The copying of the trace_seq to the seq_file buffer will fail if the
    seq_file buffer is full. The seq_read will not show this entry.
    The next read by userspace will cause seq_read to again call s_start
    which will reuse the trace iterator entry (the function start entry).
    But the function return entry was already consumed. The function graph
    plugin will think that this entry is a nested function and not a leaf.
    
    To solve this, the trace code now checks the return status of the
    seq_printf (trace_print_seq). If the writing to the seq_file buffer
    fails, we set a flag in the iterator (leftover) and we do not reset
    the trace_seq buffer. On the next call to s_start, we check the leftover
    flag, and if it is set, we just reuse the trace_seq buffer and do not
    call into the plugin print functions.
    
    Before this patch:
    
     2)               |      fput() {
     2)               |        __fput() {
     2)   0.550 us    |          inotify_inode_queue_event();
     2)               |          __fsnotify_parent() {
     2)   0.540 us    |          inotify_dentry_parent_queue_event();
    
    After the patch:
    
     2)               |      fput() {
     2)               |        __fput() {
     2)   0.550 us    |          inotify_inode_queue_event();
     2)   0.548 us    |          __fsnotify_parent();
     2)   0.540 us    |          inotify_dentry_parent_queue_event();
    
    [
      Updated the patch to fix a missing return 0 from the trace_print_seq()
      stub when CONFIG_TRACING is disabled.
    
    Reported-by: default avatarIngo Molnar <mingo@elte.hu>
    ]
    
    Reported-by: default avatarJiri Olsa <jolsa@redhat.com>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
    a63ce5b3