]> Git Repo - linux.git/commitdiff
Merge tag 'trace-seq-buf-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/roste...
authorLinus Torvalds <[email protected]>
Thu, 11 Dec 2014 04:35:41 +0000 (20:35 -0800)
committerLinus Torvalds <[email protected]>
Thu, 11 Dec 2014 04:35:41 +0000 (20:35 -0800)
Pull nmi-safe seq_buf printk update from Steven Rostedt:
 "This code is a fork from the trace-3.19 pull as it needed the
  trace_seq clean ups from that branch.

  This code solves the issue of performing stack dumps from NMI context.
  The issue is that printk() is not safe from NMI context as if the NMI
  were to trigger when a printk() was being performed, the NMI could
  deadlock from the printk() internal locks.  This has been seen in
  practice.

  With lots of review from Petr Mladek, this code went through several
  iterations, and we feel that it is now at a point of quality to be
  accepted into mainline.

  Here's what is contained in this patch set:

   - Creates a "seq_buf" generic buffer utility that allows a descriptor
     to be passed around where functions can write their own "printk()"
     formatted strings into it.  The generic version was pulled out of
     the trace_seq() code that was made specifically for tracing.

   - The seq_buf code was change to model the seq_file code.  I have a
     patch (not included for 3.19) that converts the seq_file.c code
     over to use seq_buf.c like the trace_seq.c code does.  This was
     done to make sure that seq_buf.c is compatible with seq_file.c.  I
     may try to get that patch in for 3.20.

   - The seq_buf.c file was moved to lib/ to remove it from being
     dependent on CONFIG_TRACING.

   - The printk() was updated to allow for a per_cpu "override" of the
     internal calls.  That is, instead of writing to the console, a call
     to printk() may do something else.  This made it easier to allow
     the NMI to change what printk() does in order to call dump_stack()
     without needing to update that code as well.

   - Finally, the dump_stack from all CPUs via NMI code was converted to
     use the seq_buf code.  The caller to trigger the NMI code would
     wait till all the NMIs finished, and then it would print the
     seq_buf data to the console safely from a non NMI context

  One added bonus is that this code also makes the NMI dump stack work
  on PREEMPT_RT kernels.  As printk() includes sleeping locks on
  PREEMPT_RT, printk() only writes to console if the console does not
  use any rt_mutex converted spin locks.  Which a lot do"

* tag 'trace-seq-buf-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  x86/nmi: Fix use of unallocated cpumask_var_t
  printk/percpu: Define printk_func when printk is not defined
  x86/nmi: Perform a safe NMI stack trace on all CPUs
  printk: Add per_cpu printk func to allow printk to be diverted
  seq_buf: Move the seq_buf code to lib/
  seq-buf: Make seq_buf_bprintf() conditional on CONFIG_BINARY_PRINTF
  tracing: Add seq_buf_get_buf() and seq_buf_commit() helper functions
  tracing: Have seq_buf use full buffer
  seq_buf: Add seq_buf_can_fit() helper function
  tracing: Add paranoid size check in trace_printk_seq()
  tracing: Use trace_seq_used() and seq_buf_used() instead of len
  tracing: Clean up tracing_fill_pipe_page()
  seq_buf: Create seq_buf_used() to find out how much was written
  tracing: Add a seq_buf_clear() helper and clear len and readpos in init
  tracing: Convert seq_buf fields to be like seq_file fields
  tracing: Convert seq_buf_path() to be like seq_path()
  tracing: Create seq_buf layer in trace_seq

1  2 
include/linux/printk.h
kernel/printk/printk.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_functions_graph.c
lib/Makefile

diff --combined include/linux/printk.h
index 3dd489f2dedc264eb57dc6e613669307d4a861e9,c69be9ee8f48dd6525209d9c1cf5615e95cf379d..c8f170324e643ccb895dacfd9b06a66a8afa7193
@@@ -118,11 -118,14 +118,13 @@@ int no_printk(const char *fmt, ...
  #ifdef CONFIG_EARLY_PRINTK
  extern asmlinkage __printf(1, 2)
  void early_printk(const char *fmt, ...);
 -void early_vprintk(const char *fmt, va_list ap);
  #else
  static inline __printf(1, 2) __cold
  void early_printk(const char *s, ...) { }
  #endif
  
+ typedef int(*printk_func_t)(const char *fmt, va_list args);
  #ifdef CONFIG_PRINTK
  asmlinkage __printf(5, 0)
  int vprintk_emit(int facility, int level,
diff --combined kernel/printk/printk.c
index ea27c019655a524f7e9c5dd20b9e8c5bca5b1fa9,5af2b8bc88f0029fde42746c6553d88f6f20341d..f900dc9f682240827840d8d9d7df65830474cc44
@@@ -62,6 -62,9 +62,6 @@@ int console_printk[4] = 
        CONSOLE_LOGLEVEL_DEFAULT,       /* default_console_loglevel */
  };
  
 -/* Deferred messaged from sched code are marked by this special level */
 -#define SCHED_MESSAGE_LOGLEVEL -2
 -
  /*
   * Low level drivers may need that to know if they can schedule in
   * their unblank() callback or not. So let's export it.
@@@ -477,7 -480,7 +477,7 @@@ static int syslog_action_restricted(in
               type != SYSLOG_ACTION_SIZE_BUFFER;
  }
  
 -static int check_syslog_permissions(int type, bool from_file)
 +int check_syslog_permissions(int type, bool from_file)
  {
        /*
         * If this is from /proc/kmsg and we've already opened it, then we've
@@@ -1256,7 -1259,7 +1256,7 @@@ static int syslog_print_all(char __use
  int do_syslog(int type, char __user *buf, int len, bool from_file)
  {
        bool clear = false;
 -      static int saved_console_loglevel = -1;
 +      static int saved_console_loglevel = LOGLEVEL_DEFAULT;
        int error;
  
        error = check_syslog_permissions(type, from_file);
                break;
        /* Disable logging to console */
        case SYSLOG_ACTION_CONSOLE_OFF:
 -              if (saved_console_loglevel == -1)
 +              if (saved_console_loglevel == LOGLEVEL_DEFAULT)
                        saved_console_loglevel = console_loglevel;
                console_loglevel = minimum_console_loglevel;
                break;
        /* Enable logging to console */
        case SYSLOG_ACTION_CONSOLE_ON:
 -              if (saved_console_loglevel != -1) {
 +              if (saved_console_loglevel != LOGLEVEL_DEFAULT) {
                        console_loglevel = saved_console_loglevel;
 -                      saved_console_loglevel = -1;
 +                      saved_console_loglevel = LOGLEVEL_DEFAULT;
                }
                break;
        /* Set level of messages printed to console */
                        len = minimum_console_loglevel;
                console_loglevel = len;
                /* Implicitly re-enable logging to console */
 -              saved_console_loglevel = -1;
 +              saved_console_loglevel = LOGLEVEL_DEFAULT;
                error = 0;
                break;
        /* Number of chars in the log buffer */
@@@ -1624,10 -1627,10 +1624,10 @@@ asmlinkage int vprintk_emit(int facilit
        int printed_len = 0;
        bool in_sched = false;
        /* cpu currently holding logbuf_lock in this function */
 -      static volatile unsigned int logbuf_cpu = UINT_MAX;
 +      static unsigned int logbuf_cpu = UINT_MAX;
  
 -      if (level == SCHED_MESSAGE_LOGLEVEL) {
 -              level = -1;
 +      if (level == LOGLEVEL_SCHED) {
 +              level = LOGLEVEL_DEFAULT;
                in_sched = true;
        }
  
                        const char *end_of_header = printk_skip_level(text);
                        switch (kern_level) {
                        case '0' ... '7':
 -                              if (level == -1)
 +                              if (level == LOGLEVEL_DEFAULT)
                                        level = kern_level - '0';
 +                              /* fallthrough */
                        case 'd':       /* KERN_DEFAULT */
                                lflags |= LOG_PREFIX;
                        }
                }
        }
  
 -      if (level == -1)
 +      if (level == LOGLEVEL_DEFAULT)
                level = default_message_loglevel;
  
        if (dict)
@@@ -1786,7 -1788,7 +1786,7 @@@ EXPORT_SYMBOL(vprintk_emit)
  
  asmlinkage int vprintk(const char *fmt, va_list args)
  {
 -      return vprintk_emit(0, -1, NULL, 0, fmt, args);
 +      return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
  }
  EXPORT_SYMBOL(vprintk);
  
@@@ -1805,6 -1807,30 +1805,30 @@@ asmlinkage int printk_emit(int facility
  }
  EXPORT_SYMBOL(printk_emit);
  
 -      r = vprintk_emit(0, -1, NULL, 0, fmt, args);
+ int vprintk_default(const char *fmt, va_list args)
+ {
+       int r;
+ #ifdef CONFIG_KGDB_KDB
+       if (unlikely(kdb_trap_printk)) {
+               r = vkdb_printf(fmt, args);
+               return r;
+       }
+ #endif
++      r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
+       return r;
+ }
+ EXPORT_SYMBOL_GPL(vprintk_default);
+ /*
+  * This allows printk to be diverted to another function per cpu.
+  * This is useful for calling printk functions from within NMI
+  * without worrying about race conditions that can lock up the
+  * box.
+  */
+ DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
  /**
   * printk - print a kernel message
   * @fmt: format string
   */
  asmlinkage __visible int printk(const char *fmt, ...)
  {
+       printk_func_t vprintk_func;
        va_list args;
        int r;
  
- #ifdef CONFIG_KGDB_KDB
-       if (unlikely(kdb_trap_printk)) {
-               va_start(args, fmt);
-               r = vkdb_printf(fmt, args);
-               va_end(args);
-               return r;
-       }
- #endif
        va_start(args, fmt);
-       r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
+       preempt_disable();
+       vprintk_func = this_cpu_read(printk_func);
+       r = vprintk_func(fmt, args);
+       preempt_enable();
        va_end(args);
  
        return r;
@@@ -1874,25 -1896,31 +1894,28 @@@ static size_t msg_print_text(const stru
                             bool syslog, char *buf, size_t size) { return 0; }
  static size_t cont_print_text(char *text, size_t size) { return 0; }
  
+ /* Still needs to be defined for users */
+ DEFINE_PER_CPU(printk_func_t, printk_func);
  #endif /* CONFIG_PRINTK */
  
  #ifdef CONFIG_EARLY_PRINTK
  struct console *early_console;
  
 -void early_vprintk(const char *fmt, va_list ap)
 -{
 -      if (early_console) {
 -              char buf[512];
 -              int n = vscnprintf(buf, sizeof(buf), fmt, ap);
 -
 -              early_console->write(early_console, buf, n);
 -      }
 -}
 -
  asmlinkage __visible void early_printk(const char *fmt, ...)
  {
        va_list ap;
 +      char buf[512];
 +      int n;
 +
 +      if (!early_console)
 +              return;
  
        va_start(ap, fmt);
 -      early_vprintk(fmt, ap);
 +      n = vscnprintf(buf, sizeof(buf), fmt, ap);
        va_end(ap);
 +
 +      early_console->write(early_console, buf, n);
  }
  #endif
  
@@@ -2629,7 -2657,7 +2652,7 @@@ int printk_deferred(const char *fmt, ..
  
        preempt_disable();
        va_start(args, fmt);
 -      r = vprintk_emit(0, SCHED_MESSAGE_LOGLEVEL, NULL, 0, fmt, args);
 +      r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args);
        va_end(args);
  
        __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
diff --combined kernel/trace/trace.c
index ce11fa50a2f01de7cfa01eef4ffecd2c0e6c98a8,26facec4625e205ce2cbed6dbc1bad13e3ec9a40..1af4f8f2ab5d167d01d1a13af72f0250fe4377ff
@@@ -939,19 -939,20 +939,20 @@@ out
        return ret;
  }
  
+ /* TODO add a seq_buf_to_buffer() */
  static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
  {
        int len;
  
-       if (s->len <= s->readpos)
+       if (trace_seq_used(s) <= s->seq.readpos)
                return -EBUSY;
  
-       len = s->len - s->readpos;
+       len = trace_seq_used(s) - s->seq.readpos;
        if (cnt > len)
                cnt = len;
-       memcpy(buf, s->buffer + s->readpos, cnt);
+       memcpy(buf, s->buffer + s->seq.readpos, cnt);
  
-       s->readpos += cnt;
+       s->seq.readpos += cnt;
        return cnt;
  }
  
@@@ -1077,14 -1078,13 +1078,14 @@@ update_max_tr_single(struct trace_arra
  }
  #endif /* CONFIG_TRACER_MAX_TRACE */
  
 -static int wait_on_pipe(struct trace_iterator *iter)
 +static int wait_on_pipe(struct trace_iterator *iter, bool full)
  {
        /* Iterators are static, they should be filled or empty */
        if (trace_buffer_iter(iter, iter->cpu_file))
                return 0;
  
 -      return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
 +      return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file,
 +                              full);
  }
  
  #ifdef CONFIG_FTRACE_STARTUP_TEST
@@@ -2159,7 -2159,9 +2160,7 @@@ __trace_array_vprintk(struct ring_buffe
                goto out;
        }
  
 -      len = vsnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
 -      if (len > TRACE_BUF_SIZE)
 -              goto out;
 +      len = vscnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
  
        local_save_flags(flags);
        size = sizeof(*entry) + len + 1;
        entry = ring_buffer_event_data(event);
        entry->ip = ip;
  
 -      memcpy(&entry->buf, tbuffer, len);
 -      entry->buf[len] = '\0';
 +      memcpy(&entry->buf, tbuffer, len + 1);
        if (!call_filter_check_discard(call, entry, buffer, event)) {
                __buffer_unlock_commit(buffer, event);
                ftrace_trace_stack(buffer, flags, 6, pc);
@@@ -4313,6 -4316,8 +4314,8 @@@ static int tracing_open_pipe(struct ino
                goto out;
        }
  
+       trace_seq_init(&iter->seq);
        /*
         * We make a copy of the current tracer to avoid concurrent
         * changes on it while we are reading.
@@@ -4434,12 -4439,15 +4437,12 @@@ static int tracing_wait_pipe(struct fil
  
                mutex_unlock(&iter->mutex);
  
 -              ret = wait_on_pipe(iter);
 +              ret = wait_on_pipe(iter, false);
  
                mutex_lock(&iter->mutex);
  
                if (ret)
                        return ret;
 -
 -              if (signal_pending(current))
 -                      return -EINTR;
        }
  
        return 1;
@@@ -4506,18 -4514,18 +4509,18 @@@ waitagain
        trace_access_lock(iter->cpu_file);
        while (trace_find_next_entry_inc(iter) != NULL) {
                enum print_line_t ret;
-               int len = iter->seq.len;
+               int save_len = iter->seq.seq.len;
  
                ret = print_trace_line(iter);
                if (ret == TRACE_TYPE_PARTIAL_LINE) {
                        /* don't print partial lines */
-                       iter->seq.len = len;
+                       iter->seq.seq.len = save_len;
                        break;
                }
                if (ret != TRACE_TYPE_NO_CONSUME)
                        trace_consume(iter);
  
-               if (iter->seq.len >= cnt)
+               if (trace_seq_used(&iter->seq) >= cnt)
                        break;
  
                /*
  
        /* Now copy what we have to the user */
        sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
-       if (iter->seq.readpos >= iter->seq.len)
+       if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq))
                trace_seq_init(&iter->seq);
  
        /*
@@@ -4567,20 -4575,33 +4570,33 @@@ static size_
  tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter)
  {
        size_t count;
+       int save_len;
        int ret;
  
        /* Seq buffer is page-sized, exactly what we need. */
        for (;;) {
-               count = iter->seq.len;
+               save_len = iter->seq.seq.len;
                ret = print_trace_line(iter);
-               count = iter->seq.len - count;
-               if (rem < count) {
-                       rem = 0;
-                       iter->seq.len -= count;
+               if (trace_seq_has_overflowed(&iter->seq)) {
+                       iter->seq.seq.len = save_len;
                        break;
                }
+               /*
+                * This should not be hit, because it should only
+                * be set if the iter->seq overflowed. But check it
+                * anyway to be safe.
+                */
                if (ret == TRACE_TYPE_PARTIAL_LINE) {
-                       iter->seq.len -= count;
+                       iter->seq.seq.len = save_len;
+                       break;
+               }
+               count = trace_seq_used(&iter->seq) - save_len;
+               if (rem < count) {
+                       rem = 0;
+                       iter->seq.seq.len = save_len;
                        break;
                }
  
@@@ -4661,13 -4682,13 +4677,13 @@@ static ssize_t tracing_splice_read_pipe
                /* Copy the data into the page, so we can start over. */
                ret = trace_seq_to_buffer(&iter->seq,
                                          page_address(spd.pages[i]),
-                                         iter->seq.len);
+                                         trace_seq_used(&iter->seq));
                if (ret < 0) {
                        __free_page(spd.pages[i]);
                        break;
                }
                spd.partial[i].offset = 0;
-               spd.partial[i].len = iter->seq.len;
+               spd.partial[i].len = trace_seq_used(&iter->seq);
  
                trace_seq_init(&iter->seq);
        }
@@@ -5369,12 -5390,16 +5385,12 @@@ tracing_buffers_read(struct file *filp
                                goto out_unlock;
                        }
                        mutex_unlock(&trace_types_lock);
 -                      ret = wait_on_pipe(iter);
 +                      ret = wait_on_pipe(iter, false);
                        mutex_lock(&trace_types_lock);
                        if (ret) {
                                size = ret;
                                goto out_unlock;
                        }
 -                      if (signal_pending(current)) {
 -                              size = -EINTR;
 -                              goto out_unlock;
 -                      }
                        goto again;
                }
                size = 0;
@@@ -5493,7 -5518,7 +5509,7 @@@ tracing_buffers_splice_read(struct fil
        };
        struct buffer_ref *ref;
        int entries, size, i;
 -      ssize_t ret;
 +      ssize_t ret = 0;
  
        mutex_lock(&trace_types_lock);
  
                int r;
  
                ref = kzalloc(sizeof(*ref), GFP_KERNEL);
 -              if (!ref)
 +              if (!ref) {
 +                      ret = -ENOMEM;
                        break;
 +              }
  
                ref->ref = 1;
                ref->buffer = iter->trace_buffer->buffer;
                ref->page = ring_buffer_alloc_read_page(ref->buffer, iter->cpu_file);
                if (!ref->page) {
 +                      ret = -ENOMEM;
                        kfree(ref);
                        break;
                }
  
        /* did we read anything? */
        if (!spd.nr_pages) {
 +              if (ret)
 +                      goto out;
 +
                if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) {
                        ret = -EAGAIN;
                        goto out;
                }
                mutex_unlock(&trace_types_lock);
 -              ret = wait_on_pipe(iter);
 +              ret = wait_on_pipe(iter, true);
                mutex_lock(&trace_types_lock);
                if (ret)
                        goto out;
 -              if (signal_pending(current)) {
 -                      ret = -EINTR;
 -                      goto out;
 -              }
 +
                goto again;
        }
  
@@@ -5667,7 -5689,8 +5683,8 @@@ tracing_stats_read(struct file *filp, c
        cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu);
        trace_seq_printf(s, "read events: %ld\n", cnt);
  
-       count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
+       count = simple_read_from_buffer(ubuf, count, ppos,
+                                       s->buffer, trace_seq_used(s));
  
        kfree(s);
  
@@@ -6416,7 -6439,7 +6433,7 @@@ static int instance_mkdir (struct inod
        int ret;
  
        /* Paranoid: Make sure the parent is the "instances" directory */
 -      parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
 +      parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
  
@@@ -6443,7 -6466,7 +6460,7 @@@ static int instance_rmdir(struct inode 
        int ret;
  
        /* Paranoid: Make sure the parent is the "instances" directory */
 -      parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
 +      parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
  
  trace_printk_seq(struct trace_seq *s)
  {
        /* Probably should print a warning here. */
-       if (s->len >= TRACE_MAX_PRINT)
-               s->len = TRACE_MAX_PRINT;
+       if (s->seq.len >= TRACE_MAX_PRINT)
+               s->seq.len = TRACE_MAX_PRINT;
+       /*
+        * More paranoid code. Although the buffer size is set to
+        * PAGE_SIZE, and TRACE_MAX_PRINT is 1000, this is just
+        * an extra layer of protection.
+        */
+       if (WARN_ON_ONCE(s->seq.len >= s->seq.size))
+               s->seq.len = s->seq.size - 1;
  
        /* should be zero ended, but we are paranoid. */
-       s->buffer[s->len] = 0;
+       s->buffer[s->seq.len] = 0;
  
        printk(KERN_TRACE "%s", s->buffer);
  
index 139716bcef7a5eccaf620040e7433aca3597ee77,935cbea7853284f565a726df58413833436c8884..d0e4f92b5eb6c6d46e9524a2c409e265ab4e2513
@@@ -461,7 -461,7 +461,7 @@@ static void remove_event_file_dir(struc
  
        if (dir) {
                spin_lock(&dir->d_lock);        /* probably unneeded */
 -              list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
 +              list_for_each_entry(child, &dir->d_subdirs, d_child) {
                        if (child->d_inode)     /* probably unneeded */
                                child->d_inode->i_private = NULL;
                }
@@@ -1044,7 -1044,8 +1044,8 @@@ event_filter_read(struct file *filp, ch
        mutex_unlock(&event_mutex);
  
        if (file)
-               r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+               r = simple_read_from_buffer(ubuf, cnt, ppos,
+                                           s->buffer, trace_seq_used(s));
  
        kfree(s);
  
@@@ -1210,7 -1211,8 +1211,8 @@@ subsystem_filter_read(struct file *filp
        trace_seq_init(s);
  
        print_subsystem_event_filter(system, s);
-       r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+       r = simple_read_from_buffer(ubuf, cnt, ppos,
+                                   s->buffer, trace_seq_used(s));
  
        kfree(s);
  
@@@ -1265,7 -1267,8 +1267,8 @@@ show_header(struct file *filp, char __u
        trace_seq_init(s);
  
        func(s);
-       r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+       r = simple_read_from_buffer(ubuf, cnt, ppos,
+                                   s->buffer, trace_seq_used(s));
  
        kfree(s);
  
index 6c2ab955018c24d6fa42402f8d6c305640da26f9,ec35468349a7aa217a719eda46e1c7b60b15efa4..ba476009e5de49a89321f7b1d31f2e0d0d5bd63b
@@@ -730,6 -730,8 +730,6 @@@ static voi
  print_graph_duration(unsigned long long duration, struct trace_seq *s,
                     u32 flags)
  {
 -      bool duration_printed = false;
 -
        if (!(flags & TRACE_GRAPH_PRINT_DURATION) ||
            !(trace_flags & TRACE_ITER_CONTEXT_INFO))
                return;
        }
  
        /* Signal a overhead of time execution to the output */
 -      if (flags & TRACE_GRAPH_PRINT_OVERHEAD) {
 -              /* Duration exceeded 100 usecs */
 -              if (duration > 100000ULL) {
 -                      trace_seq_puts(s, "! ");
 -                      duration_printed = true;
 -
 -              /* Duration exceeded 10 usecs */
 -              } else if (duration > 10000ULL) {
 -                      trace_seq_puts(s, "+ ");
 -                      duration_printed = true;
 -              }
 -      }
 -
 -      /*
 -       * If we did not exceed the duration tresholds or we dont want
 -       * to print out the overhead. Either way we need to fill out the space.
 -       */
 -      if (!duration_printed)
 +      if (flags & TRACE_GRAPH_PRINT_OVERHEAD)
 +              trace_seq_printf(s, "%c ", trace_find_mark(duration));
 +      else
                trace_seq_puts(s, "  ");
  
        trace_print_graph_duration(duration, s);
@@@ -1136,14 -1153,17 +1136,17 @@@ print_graph_comment(struct trace_seq *s
                        return ret;
        }
  
+       if (trace_seq_has_overflowed(s))
+               goto out;
        /* Strip ending newline */
-       if (s->buffer[s->len - 1] == '\n') {
-               s->buffer[s->len - 1] = '\0';
-               s->len--;
+       if (s->buffer[s->seq.len - 1] == '\n') {
+               s->buffer[s->seq.len - 1] = '\0';
+               s->seq.len--;
        }
  
        trace_seq_puts(s, " */\n");
+  out:
        return trace_handle_return(s);
  }
  
diff --combined lib/Makefile
index 0211d2bd5e17551856da7ca97aea0849528b2ead,a1aa1e81ed367ff6f7aa35adcca7eafdf9e0c164..923a191eaf7163559e19cc6bebe5ad2a4489c280
@@@ -10,10 -10,10 +10,10 @@@ endi
  lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o dump_stack.o timerqueue.o\
         idr.o int_sqrt.o extable.o \
 -       sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
 +       sha1.o md5.o irq_regs.o argv_split.o \
         proportions.o flex_proportions.o ratelimit.o show_mem.o \
         is_single_threaded.o plist.o decompress.o kobject_uevent.o \
-        earlycpio.o
+        earlycpio.o seq_buf.o
  
  obj-$(CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS) += usercopy.o
  lib-$(CONFIG_MMU) += ioremap.o
@@@ -26,7 -26,7 +26,7 @@@ obj-y += bcd.o div64.o sort.o parser.o 
         bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
         gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o clz_ctz.o \
         bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \
 -       percpu-refcount.o percpu_ida.o hash.o rhashtable.o
 +       percpu-refcount.o percpu_ida.o hash.o rhashtable.o reciprocal_div.o
  obj-y += string_helpers.o
  obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
  obj-y += kstrtox.o
This page took 0.126465 seconds and 4 git commands to generate.