/* * ring buffer based function tracer * * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com> * * Originally taken from the RT patch by: * Arnaldo Carvalho de Melo <acme@redhat.com> * * Based on code from the latency_tracer, that is: * Copyright (C) 2004-2006 Ingo Molnar * Copyright (C) 2004 William Lee Irwin III */#include <linux/utsrelease.h>#include <linux/kallsyms.h>#include <linux/seq_file.h>#include <linux/notifier.h>#include <linux/debugfs.h>#include <linux/pagemap.h>#include <linux/hardirq.h>#include <linux/linkage.h>#include <linux/uaccess.h>#include <linux/ftrace.h>#include <linux/module.h>#include <linux/percpu.h>#include <linux/kdebug.h>#include <linux/ctype.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/gfp.h>#include <linux/fs.h>#include <linux/kprobes.h>#include <linux/writeback.h> #include <linux/stacktrace.h>#include <linux/ring_buffer.h>#include <linux/irqflags.h> #include "trace.h" #define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE) unsigned long __read_mostly tracing_max_latency;unsigned long __read_mostly tracing_thresh; /* * We need to change this state when a selftest is running. * A selftest will lurk into the ring-buffer to count the * entries inserted during the selftest although some concurrent * insertions into the ring-buffer such as ftrace_printk could occurred * at the same time, giving false positive or negative results. */static bool __read_mostly tracing_selftest_running; /* For tracers that don't implement custom flags */static struct tracer_opt dummy_tracer_opt[] = { { }}; static struct tracer_flags dummy_tracer_flags = { .val = 0, .opts = dummy_tracer_opt}; static int dummy_set_flag(u32 old_flags, u32 bit, int set){ return 0;} /* * Kill all tracing for good (never come back). * It is initialized to 1 but will turn to zero if the initialization * of the tracer is successful. But that is the only place that sets * this back to zero. */int tracing_disabled = 1; static DEFINE_PER_CPU(local_t, ftrace_cpu_disabled); static inline void ftrace_disable_cpu(void){ preempt_disable(); local_inc(&__get_cpu_var(ftrace_cpu_disabled));} static inline void ftrace_enable_cpu(void){ local_dec(&__get_cpu_var(ftrace_cpu_disabled)); preempt_enable();} static cpumask_var_t __read_mostly tracing_buffer_mask; #define for_each_tracing_cpu(cpu) \ for_each_cpu(cpu, tracing_buffer_mask) /* * ftrace_dump_on_oops - variable to dump ftrace buffer on oops * * If there is an oops (or kernel panic) and the ftrace_dump_on_oops * is set, then ftrace_dump is called. This will output the contents * of the ftrace buffers to the console. This is very useful for * capturing traces that lead to crashes and outputing it to a * serial console. * * It is default off, but you can enable it with either specifying * "ftrace_dump_on_oops" in the kernel command line, or setting * /proc/sys/kernel/ftrace_dump_on_oops to true. */int ftrace_dump_on_oops; static int tracing_set_tracer(char *buf); static int __init set_ftrace(char *str){ tracing_set_tracer(str); return 1;}__setup("ftrace", set_ftrace); static int __init set_ftrace_dump_on_oops(char *str){ ftrace_dump_on_oops = 1; return 1;}__setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); longns2usecs(cycle_t nsec){ nsec += 500; do_div(nsec, 1000); return nsec;} cycle_t ftrace_now(int cpu){ u64 ts = ring_buffer_time_stamp(cpu); ring_buffer_normalize_time_stamp(cpu, &ts); return ts;} /* * The global_trace is the descriptor that holds the tracing * buffers for the live tracing. For each CPU, it contains * a link list of pages that will store trace entries. The * page descriptor of the pages in the memory is used to hold * the link list by linking the lru item in the page descriptor * to each of the pages in the buffer per CPU. * * For each active CPU there is a data field that holds the * pages for the buffer for that CPU. Each CPU has the same number * of pages allocated for its buffer. */static struct trace_array global_trace; static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu); /* * The max_tr is used to snapshot the global_trace when a maximum * latency is reached. Some tracers will use this to store a maximum * trace while it continues examining live traces. * * The buffers for the max_tr are set up the same as the global_trace. * When a snapshot is taken, the link list of the max_tr is swapped * with the link list of the global_trace and the buffers are reset for * the global_trace so the tracing can continue. */static struct trace_array max_tr; static DEFINE_PER_CPU(struct trace_array_cpu, max_data); /* tracer_enabled is used to toggle activation of a tracer */static int tracer_enabled = 1; /** * tracing_is_enabled - return tracer_enabled status * * This function is used by other tracers to know the status * of the tracer_enabled flag. Tracers may use this function * to know if it should enable their features when starting * up. See irqsoff tracer for an example (start_irqsoff_tracer). */int tracing_is_enabled(void){ return tracer_enabled;} /* function tracing enabled */int ftrace_function_enabled; /* * trace_buf_size is the size in bytes that is allocated * for a buffer. Note, the number of bytes is always rounded * to page size. * * This number is purposely set to a low number of 16384. * If the dump on oops happens, it will be much appreciated * to not have to wait for all that output. Anyway this can be * boot time and run time configurable. */#define TRACE_BUF_SIZE_DEFAULT 1441792UL /* 16384 * 88 (sizeof(entry)) */ static unsigned long trace_buf_size = TRACE_BUF_SIZE_DEFAULT; /* trace_types holds a link list of available tracers. */static struct tracer *trace_types __read_mostly; /* current_trace points to the tracer that is currently active */static struct tracer *current_trace __read_mostly; /* * max_tracer_type_len is used to simplify the allocating of * buffers to read userspace tracer names. We keep track of * the longest tracer name registered. */static int max_tracer_type_len; /* * trace_types_lock is used to protect the trace_types list. * This lock is also used to keep user access serialized. * Accesses from userspace will grab this lock while userspace * activities happen inside the kernel. */static DEFINE_MUTEX(trace_types_lock); /* trace_wait is a waitqueue for tasks blocked on trace_poll */static DECLARE_WAIT_QUEUE_HEAD(trace_wait); /* trace_flags holds trace_options default values */unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | TRACE_ITER_ANNOTATE; /** * trace_wake_up - wake up tasks waiting for trace input * * Simply wakes up any task that is blocked on the trace_wait * queue. These is used with trace_poll for tasks polling the trace. */void trace_wake_up(void){ /* * The runqueue_is_locked() can fail, but this is the best we * have for now: */ if (!(trace_flags & TRACE_ITER_BLOCK) && !runqueue_is_locked()) wake_up(&trace_wait);} static int __init set_buf_size(char *str){ unsigned long buf_size; int ret; if (!str) return 0; ret = strict_strtoul(str, 0, &buf_size); /* nr_entries can not be zero */ if (ret < 0 || buf_size == 0) return 0; trace_buf_size = buf_size; return 1;}__setup("trace_buf_size=", set_buf_size); unsigned long nsecs_to_usecs(unsigned long nsecs){ return nsecs / 1000;} /* These must match the bit postions in trace_iterator_flags */static const char *trace_options[] = { "print-parent", "sym-offset", "sym-addr", "verbose", "raw", "hex", "bin", "block", "stacktrace", "sched-tree", "ftrace_printk", "ftrace_preempt", "branch", "annotate", "userstacktrace", "sym-userobj", "printk-msg-only", NULL}; /* * ftrace_max_lock is used to protect the swapping of buffers * when taking a max snapshot. The buffers themselves are * protected by per_cpu spinlocks. But the action of the swap * needs its own lock. * * This is defined as a raw_spinlock_t in order to help * with performance when lockdep debugging is enabled. */static raw_spinlock_t ftrace_max_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; /* * Copy the new maximum trace into the separate maximum-trace * structure. (this way the maximum trace is permanently saved, * for later retrieval via /debugfs/tracing/latency_trace) */static void__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu){ struct trace_array_cpu *data = tr->data[cpu]; max_tr.cpu = cpu; max_tr.time_start = data->preempt_timestamp; data = max_tr.data[cpu]; data->saved_latency = tracing_max_latency; memcpy(data->comm, tsk->comm, TASK_COMM_LEN); data->pid = tsk->pid; data->uid = task_uid(tsk); data->nice = tsk->static_prio - 20 - MAX_RT_PRIO; data->policy = tsk->policy; data->rt_priority = tsk->rt_priority; /* record this tasks comm */ tracing_record_cmdline(current);} /** * trace_seq_printf - sequence printing of trace information * @s: trace sequence descriptor * @fmt: printf format string * * The tracer may use either sequence operations or its own * copy to user routines. To simplify formating of a trace * trace_seq_printf is used to store strings into a special * buffer (@s). Then the output may be either used by * the sequencer or pulled into another buffer. */inttrace_seq_printf(struct trace_seq *s, const char *fmt, ...){ int len = (PAGE_SIZE - 1) - s->len; va_list ap; int ret; if (!len) return 0; va_start(ap, fmt); ret = vsnprintf(s->buffer + s->len, len, fmt, ap); va_end(ap); /* If we can't write it all, don't bother writing anything */ if (ret >= len) return 0; s->len += ret; return len;} /** * trace_seq_puts - trace sequence printing of simple string * @s: trace sequence descriptor * @str: simple string to record * * The tracer may use either the sequence operations or its own * copy to user routines. This function records a simple string * into a special buffer (@s) for later retrieval by a sequencer * or other mechanism. */static inttrace_seq_puts(struct trace_seq *s, const char *str){ int len = strlen(str); if (len > ((PAGE_SIZE - 1) - s->len)) return 0; memcpy(s->buffer + s->len, str, len); s->len += len; return len;} static inttrace_seq_putc(struct trace_seq *s, unsigned char c){ if (s->len >= (PAGE_SIZE - 1)) return 0; s->buffer[s->len++] = c; return 1;} static inttrace_seq_putmem(struct trace_seq *s, void *mem, size_t len){ if (len > ((PAGE_SIZE - 1) - s->len)) return 0; memcpy(s->buffer + s->len, mem, len); s->len += len; return len;} #define MAX_MEMHEX_BYTES 8#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) static inttrace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len){ unsigned char hex[HEX_CHARS]; unsigned char *data = mem; int i, j; #ifdef __BIG_ENDIAN for (i = 0, j = 0; i < len; i++) {#else for (i = len-1, j = 0; i >= 0; i--) {#endif hex[j++] = hex_asc_hi(data[i]); hex[j++] = hex_asc_lo(data[i]); } hex[j++] = ' '; return trace_seq_putmem(s, hex, j);} static inttrace_seq_path(struct trace_seq *s, struct path *path){ unsigned char *p; if (s->len >= (PAGE_SIZE - 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"); if (p) { s->len = p - s->buffer; return 1; } } else { s->buffer[s->len++] = '?'; return 1; } return 0;} static voidtrace_seq_reset(struct trace_seq *s){ s->len = 0; s->readpos = 0;} ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt){ int len; int ret; if (s->len <= s->readpos) return -EBUSY; len = s->len - s->readpos; if (cnt > len) cnt = len; ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt); if (ret) return -EFAULT; s->readpos += len; return cnt;} static voidtrace_print_seq(struct seq_file *m, struct trace_seq *s){ int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; s->buffer[len] = 0; seq_puts(m, s->buffer); trace_seq_reset(s);} /** * update_max_tr - snapshot all trace buffers from global_trace to max_tr * @tr: tracer * @tsk: the task with the latency * @cpu: The cpu that initiated the trace. *Lines 1–500 of 3899. Load more
/* * ring buffer based function tracer * * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com> * * Originally taken from the RT patch by: * Arnaldo Carvalho de Melo <acme@redhat.com> * * Based on code from the latency_tracer, that is: * Copyright (C) 2004-2006 Ingo Molnar * Copyright (C) 2004 William Lee Irwin III */ #include <linux/utsrelease.h> #include <linux/kallsyms.h> #include <linux/seq_file.h> #include <linux/notifier.h> #include <linux/debugfs.h> #include <linux/pagemap.h> #include <linux/hardirq.h> #include <linux/linkage.h> #include <linux/uaccess.h> #include <linux/ftrace.h> #include <linux/module.h> #include <linux/percpu.h> #include <linux/kdebug.h> #include <linux/ctype.h> #include <linux/init.h> #include <linux/poll.h> #include <linux/gfp.h> #include <linux/fs.h> #include <linux/kprobes.h> #include <linux/writeback.h> #include <linux/stacktrace.h> #include <linux/ring_buffer.h> #include <linux/irqflags.h> #include "trace.h" #define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE) unsigned long __read_mostly tracing_max_latency; unsigned long __read_mostly tracing_thresh; /* * We need to change this state when a selftest is running. * A selftest will lurk into the ring-buffer to count the * entries inserted during the selftest although some concurrent * insertions into the ring-buffer such as ftrace_printk could occurred * at the same time, giving false positive or negative results. */ static bool __read_mostly tracing_selftest_running; /* For tracers that don't implement custom flags */ static struct tracer_opt dummy_tracer_opt[] = { { } }; static struct tracer_flags dummy_tracer_flags = { .val = 0, .opts = dummy_tracer_opt }; static int dummy_set_flag(u32 old_flags, u32 bit, int set) { return 0; } /* * Kill all tracing for good (never come back). * It is initialized to 1 but will turn to zero if the initialization * of the tracer is successful. But that is the only place that sets * this back to zero. */ int tracing_disabled = 1; static DEFINE_PER_CPU(local_t, ftrace_cpu_disabled); static inline void ftrace_disable_cpu(void) { preempt_disable(); local_inc(&__get_cpu_var(ftrace_cpu_disabled)); } static inline void ftrace_enable_cpu(void) { local_dec(&__get_cpu_var(ftrace_cpu_disabled)); preempt_enable(); } static cpumask_var_t __read_mostly tracing_buffer_mask; #define for_each_tracing_cpu(cpu) \ for_each_cpu(cpu, tracing_buffer_mask) /* * ftrace_dump_on_oops - variable to dump ftrace buffer on oops * * If there is an oops (or kernel panic) and the ftrace_dump_on_oops * is set, then ftrace_dump is called. This will output the contents * of the ftrace buffers to the console. This is very useful for * capturing traces that lead to crashes and outputing it to a * serial console. * * It is default off, but you can enable it with either specifying * "ftrace_dump_on_oops" in the kernel command line, or setting * /proc/sys/kernel/ftrace_dump_on_oops to true. */ int ftrace_dump_on_oops; static int tracing_set_tracer(char *buf); static int __init set_ftrace(char *str) { tracing_set_tracer(str); return 1; } __setup("ftrace", set_ftrace); static int __init set_ftrace_dump_on_oops(char *str) { ftrace_dump_on_oops = 1; return 1; } __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); long ns2usecs(cycle_t nsec) { nsec += 500; do_div(nsec, 1000); return nsec; } cycle_t ftrace_now(int cpu) { u64 ts = ring_buffer_time_stamp(cpu); ring_buffer_normalize_time_stamp(cpu, &ts); return ts; } /* * The global_trace is the descriptor that holds the tracing * buffers for the live tracing. For each CPU, it contains * a link list of pages that will store trace entries. The * page descriptor of the pages in the memory is used to hold * the link list by linking the lru item in the page descriptor * to each of the pages in the buffer per CPU. * * For each active CPU there is a data field that holds the * pages for the buffer for that CPU. Each CPU has the same number * of pages allocated for its buffer. */ static struct trace_array global_trace; static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu); /* * The max_tr is used to snapshot the global_trace when a maximum * latency is reached. Some tracers will use this to store a maximum * trace while it continues examining live traces. * * The buffers for the max_tr are set up the same as the global_trace. * When a snapshot is taken, the link list of the max_tr is swapped * with the link list of the global_trace and the buffers are reset for * the global_trace so the tracing can continue. */ static struct trace_array max_tr; static DEFINE_PER_CPU(struct trace_array_cpu, max_data); /* tracer_enabled is used to toggle activation of a tracer */ static int tracer_enabled = 1; /** * tracing_is_enabled - return tracer_enabled status * * This function is used by other tracers to know the status * of the tracer_enabled flag. Tracers may use this function * to know if it should enable their features when starting * up. See irqsoff tracer for an example (start_irqsoff_tracer). */ int tracing_is_enabled(void) { return tracer_enabled; } /* function tracing enabled */ int ftrace_function_enabled; /* * trace_buf_size is the size in bytes that is allocated * for a buffer. Note, the number of bytes is always rounded * to page size. * * This number is purposely set to a low number of 16384. * If the dump on oops happens, it will be much appreciated * to not have to wait for all that output. Anyway this can be * boot time and run time configurable. */ #define TRACE_BUF_SIZE_DEFAULT 1441792UL /* 16384 * 88 (sizeof(entry)) */ static unsigned long trace_buf_size = TRACE_BUF_SIZE_DEFAULT; /* trace_types holds a link list of available tracers. */ static struct tracer *trace_types __read_mostly; /* current_trace points to the tracer that is currently active */ static struct tracer *current_trace __read_mostly; /* * max_tracer_type_len is used to simplify the allocating of * buffers to read userspace tracer names. We keep track of * the longest tracer name registered. */ static int max_tracer_type_len; /* * trace_types_lock is used to protect the trace_types list. * This lock is also used to keep user access serialized. * Accesses from userspace will grab this lock while userspace * activities happen inside the kernel. */ static DEFINE_MUTEX(trace_types_lock); /* trace_wait is a waitqueue for tasks blocked on trace_poll */ static DECLARE_WAIT_QUEUE_HEAD(trace_wait); /* trace_flags holds trace_options default values */ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | TRACE_ITER_ANNOTATE; /** * trace_wake_up - wake up tasks waiting for trace input * * Simply wakes up any task that is blocked on the trace_wait * queue. These is used with trace_poll for tasks polling the trace. */ void trace_wake_up(void) { /* * The runqueue_is_locked() can fail, but this is the best we * have for now: */ if (!(trace_flags & TRACE_ITER_BLOCK) && !runqueue_is_locked()) wake_up(&trace_wait); } static int __init set_buf_size(char *str) { unsigned long buf_size; int ret; if (!str) return 0; ret = strict_strtoul(str, 0, &buf_size); /* nr_entries can not be zero */ if (ret < 0 || buf_size == 0) return 0; trace_buf_size = buf_size; return 1; } __setup("trace_buf_size=", set_buf_size); unsigned long nsecs_to_usecs(unsigned long nsecs) { return nsecs / 1000; } /* These must match the bit postions in trace_iterator_flags */ static const char *trace_options[] = { "print-parent", "sym-offset", "sym-addr", "verbose", "raw", "hex", "bin", "block", "stacktrace", "sched-tree", "ftrace_printk", "ftrace_preempt", "branch", "annotate", "userstacktrace", "sym-userobj", "printk-msg-only", NULL }; /* * ftrace_max_lock is used to protect the swapping of buffers * when taking a max snapshot. The buffers themselves are * protected by per_cpu spinlocks. But the action of the swap * needs its own lock. * * This is defined as a raw_spinlock_t in order to help * with performance when lockdep debugging is enabled. */ static raw_spinlock_t ftrace_max_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; /* * Copy the new maximum trace into the separate maximum-trace * structure. (this way the maximum trace is permanently saved, * for later retrieval via /debugfs/tracing/latency_trace) */ static void __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) { struct trace_array_cpu *data = tr->data[cpu]; max_tr.cpu = cpu; max_tr.time_start = data->preempt_timestamp; data = max_tr.data[cpu]; data->saved_latency = tracing_max_latency; memcpy(data->comm, tsk->comm, TASK_COMM_LEN); data->pid = tsk->pid; data->uid = task_uid(tsk); data->nice = tsk->static_prio - 20 - MAX_RT_PRIO; data->policy = tsk->policy; data->rt_priority = tsk->rt_priority; /* record this tasks comm */ tracing_record_cmdline(current); } /** * trace_seq_printf - sequence printing of trace information * @s: trace sequence descriptor * @fmt: printf format string * * The tracer may use either sequence operations or its own * copy to user routines. To simplify formating of a trace * trace_seq_printf is used to store strings into a special * buffer (@s). Then the output may be either used by * the sequencer or pulled into another buffer. */ int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) { int len = (PAGE_SIZE - 1) - s->len; va_list ap; int ret; if (!len) return 0; va_start(ap, fmt); ret = vsnprintf(s->buffer + s->len, len, fmt, ap); va_end(ap); /* If we can't write it all, don't bother writing anything */ if (ret >= len) return 0; s->len += ret; return len; } /** * trace_seq_puts - trace sequence printing of simple string * @s: trace sequence descriptor * @str: simple string to record * * The tracer may use either the sequence operations or its own * copy to user routines. This function records a simple string * into a special buffer (@s) for later retrieval by a sequencer * or other mechanism. */ static int trace_seq_puts(struct trace_seq *s, const char *str) { int len = strlen(str); if (len > ((PAGE_SIZE - 1) - s->len)) return 0; memcpy(s->buffer + s->len, str, len); s->len += len; return len; } static int trace_seq_putc(struct trace_seq *s, unsigned char c) { if (s->len >= (PAGE_SIZE - 1)) return 0; s->buffer[s->len++] = c; return 1; } static int trace_seq_putmem(struct trace_seq *s, void *mem, size_t len) { if (len > ((PAGE_SIZE - 1) - s->len)) return 0; memcpy(s->buffer + s->len, mem, len); s->len += len; return len; } #define MAX_MEMHEX_BYTES 8 #define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) static int trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len) { unsigned char hex[HEX_CHARS]; unsigned char *data = mem; int i, j; #ifdef __BIG_ENDIAN for (i = 0, j = 0; i < len; i++) { #else for (i = len-1, j = 0; i >= 0; i--) { #endif hex[j++] = hex_asc_hi(data[i]); hex[j++] = hex_asc_lo(data[i]); } hex[j++] = ' '; return trace_seq_putmem(s, hex, j); } static int trace_seq_path(struct trace_seq *s, struct path *path) { unsigned char *p; if (s->len >= (PAGE_SIZE - 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"); if (p) { s->len = p - s->buffer; return 1; } } else { s->buffer[s->len++] = '?'; return 1; } return 0; } static void trace_seq_reset(struct trace_seq *s) { s->len = 0; s->readpos = 0; } ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) { int len; int ret; if (s->len <= s->readpos) return -EBUSY; len = s->len - s->readpos; if (cnt > len) cnt = len; ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt); if (ret) return -EFAULT; s->readpos += len; return cnt; } static void trace_print_seq(struct seq_file *m, struct trace_seq *s) { int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; s->buffer[len] = 0; seq_puts(m, s->buffer); trace_seq_reset(s); } /** * update_max_tr - snapshot all trace buffers from global_trace to max_tr * @tr: tracer * @tsk: the task with the latency * @cpu: The cpu that initiated the trace. *