Commit 72b51a6b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'tracing-fixes-for-linus' of...

Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  kernel/profile.c: fix section mismatch warning
  function tracing: fix wrong pos computing when read buffer has been fulfilled
  tracing: fix mmiotrace resizing crash
  ring-buffer: no preempt for sched_clock()
  ring-buffer: buffer record on/off switch
parents 8c60bfb0 e270219f
...@@ -120,6 +120,9 @@ unsigned long ring_buffer_overruns(struct ring_buffer *buffer); ...@@ -120,6 +120,9 @@ unsigned long ring_buffer_overruns(struct ring_buffer *buffer);
u64 ring_buffer_time_stamp(int cpu); u64 ring_buffer_time_stamp(int cpu);
void ring_buffer_normalize_time_stamp(int cpu, u64 *ts); void ring_buffer_normalize_time_stamp(int cpu, u64 *ts);
void tracing_on(void);
void tracing_off(void);
enum ring_buffer_flags { enum ring_buffer_flags {
RB_FL_OVERWRITE = 1 << 0, RB_FL_OVERWRITE = 1 << 0,
}; };
......
...@@ -544,7 +544,7 @@ static const struct file_operations proc_profile_operations = { ...@@ -544,7 +544,7 @@ static const struct file_operations proc_profile_operations = {
}; };
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void __init profile_nop(void *unused) static inline void profile_nop(void *unused)
{ {
} }
......
...@@ -185,7 +185,6 @@ enum { ...@@ -185,7 +185,6 @@ enum {
}; };
static int ftrace_filtered; static int ftrace_filtered;
static int tracing_on;
static LIST_HEAD(ftrace_new_addrs); static LIST_HEAD(ftrace_new_addrs);
...@@ -506,13 +505,10 @@ static int __ftrace_modify_code(void *data) ...@@ -506,13 +505,10 @@ static int __ftrace_modify_code(void *data)
{ {
int *command = data; int *command = data;
if (*command & FTRACE_ENABLE_CALLS) { if (*command & FTRACE_ENABLE_CALLS)
ftrace_replace_code(1); ftrace_replace_code(1);
tracing_on = 1; else if (*command & FTRACE_DISABLE_CALLS)
} else if (*command & FTRACE_DISABLE_CALLS) {
ftrace_replace_code(0); ftrace_replace_code(0);
tracing_on = 0;
}
if (*command & FTRACE_UPDATE_TRACE_FUNC) if (*command & FTRACE_UPDATE_TRACE_FUNC)
ftrace_update_ftrace_func(ftrace_trace_function); ftrace_update_ftrace_func(ftrace_trace_function);
...@@ -677,7 +673,7 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init) ...@@ -677,7 +673,7 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
cnt = num_to_init / ENTRIES_PER_PAGE; cnt = num_to_init / ENTRIES_PER_PAGE;
pr_info("ftrace: allocating %ld entries in %d pages\n", pr_info("ftrace: allocating %ld entries in %d pages\n",
num_to_init, cnt); num_to_init, cnt + 1);
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
pg->next = (void *)get_zeroed_page(GFP_KERNEL); pg->next = (void *)get_zeroed_page(GFP_KERNEL);
...@@ -757,13 +753,11 @@ static void *t_start(struct seq_file *m, loff_t *pos) ...@@ -757,13 +753,11 @@ static void *t_start(struct seq_file *m, loff_t *pos)
void *p = NULL; void *p = NULL;
loff_t l = -1; loff_t l = -1;
if (*pos != iter->pos) { if (*pos > iter->pos)
for (p = t_next(m, p, &l); p && l < *pos; p = t_next(m, p, &l)) *pos = iter->pos;
;
} else { l = *pos;
l = *pos; p = t_next(m, p, &l);
p = t_next(m, p, &l);
}
return p; return p;
} }
...@@ -774,15 +768,21 @@ static void t_stop(struct seq_file *m, void *p) ...@@ -774,15 +768,21 @@ static void t_stop(struct seq_file *m, void *p)
static int t_show(struct seq_file *m, void *v) static int t_show(struct seq_file *m, void *v)
{ {
struct ftrace_iterator *iter = m->private;
struct dyn_ftrace *rec = v; struct dyn_ftrace *rec = v;
char str[KSYM_SYMBOL_LEN]; char str[KSYM_SYMBOL_LEN];
int ret = 0;
if (!rec) if (!rec)
return 0; return 0;
kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
seq_printf(m, "%s\n", str); ret = seq_printf(m, "%s\n", str);
if (ret < 0) {
iter->pos--;
iter->idx--;
}
return 0; return 0;
} }
...@@ -808,7 +808,7 @@ ftrace_avail_open(struct inode *inode, struct file *file) ...@@ -808,7 +808,7 @@ ftrace_avail_open(struct inode *inode, struct file *file)
return -ENOMEM; return -ENOMEM;
iter->pg = ftrace_pages_start; iter->pg = ftrace_pages_start;
iter->pos = -1; iter->pos = 0;
ret = seq_open(file, &show_ftrace_seq_ops); ret = seq_open(file, &show_ftrace_seq_ops);
if (!ret) { if (!ret) {
...@@ -895,7 +895,7 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable) ...@@ -895,7 +895,7 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
if (file->f_mode & FMODE_READ) { if (file->f_mode & FMODE_READ) {
iter->pg = ftrace_pages_start; iter->pg = ftrace_pages_start;
iter->pos = -1; iter->pos = 0;
iter->flags = enable ? FTRACE_ITER_FILTER : iter->flags = enable ? FTRACE_ITER_FILTER :
FTRACE_ITER_NOTRACE; FTRACE_ITER_NOTRACE;
......
...@@ -16,14 +16,49 @@ ...@@ -16,14 +16,49 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/fs.h> #include <linux/fs.h>
#include "trace.h"
/* Global flag to disable all recording to ring buffers */
static int ring_buffers_off __read_mostly;
/**
* tracing_on - enable all tracing buffers
*
* This function enables all tracing buffers that may have been
* disabled with tracing_off.
*/
void tracing_on(void)
{
ring_buffers_off = 0;
}
/**
* tracing_off - turn off all tracing buffers
*
* This function stops all tracing buffers from recording data.
* It does not disable any overhead the tracers themselves may
* be causing. This function simply causes all recording to
* the ring buffers to fail.
*/
void tracing_off(void)
{
ring_buffers_off = 1;
}
/* Up this if you want to test the TIME_EXTENTS and normalization */ /* Up this if you want to test the TIME_EXTENTS and normalization */
#define DEBUG_SHIFT 0 #define DEBUG_SHIFT 0
/* FIXME!!! */ /* FIXME!!! */
u64 ring_buffer_time_stamp(int cpu) u64 ring_buffer_time_stamp(int cpu)
{ {
u64 time;
preempt_disable_notrace();
/* shift to debug/test normalization and TIME_EXTENTS */ /* shift to debug/test normalization and TIME_EXTENTS */
return sched_clock() << DEBUG_SHIFT; time = sched_clock() << DEBUG_SHIFT;
preempt_enable_notrace();
return time;
} }
void ring_buffer_normalize_time_stamp(int cpu, u64 *ts) void ring_buffer_normalize_time_stamp(int cpu, u64 *ts)
...@@ -503,6 +538,12 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size) ...@@ -503,6 +538,12 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
LIST_HEAD(pages); LIST_HEAD(pages);
int i, cpu; int i, cpu;
/*
* Always succeed at resizing a non-existent buffer:
*/
if (!buffer)
return size;
size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
size *= BUF_PAGE_SIZE; size *= BUF_PAGE_SIZE;
buffer_size = buffer->pages * BUF_PAGE_SIZE; buffer_size = buffer->pages * BUF_PAGE_SIZE;
...@@ -1133,6 +1174,9 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, ...@@ -1133,6 +1174,9 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
struct ring_buffer_event *event; struct ring_buffer_event *event;
int cpu, resched; int cpu, resched;
if (ring_buffers_off)
return NULL;
if (atomic_read(&buffer->record_disabled)) if (atomic_read(&buffer->record_disabled))
return NULL; return NULL;
...@@ -1249,6 +1293,9 @@ int ring_buffer_write(struct ring_buffer *buffer, ...@@ -1249,6 +1293,9 @@ int ring_buffer_write(struct ring_buffer *buffer,
int ret = -EBUSY; int ret = -EBUSY;
int cpu, resched; int cpu, resched;
if (ring_buffers_off)
return -EBUSY;
if (atomic_read(&buffer->record_disabled)) if (atomic_read(&buffer->record_disabled))
return -EBUSY; return -EBUSY;
...@@ -2070,3 +2117,69 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a, ...@@ -2070,3 +2117,69 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
return 0; return 0;
} }
static ssize_t
rb_simple_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
int *p = filp->private_data;
char buf[64];
int r;
/* !ring_buffers_off == tracing_on */
r = sprintf(buf, "%d\n", !*p);
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
}
static ssize_t
rb_simple_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
int *p = filp->private_data;
char buf[64];
long val;
int ret;
if (cnt >= sizeof(buf))
return -EINVAL;
if (copy_from_user(&buf, ubuf, cnt))
return -EFAULT;
buf[cnt] = 0;
ret = strict_strtoul(buf, 10, &val);
if (ret < 0)
return ret;
/* !ring_buffers_off == tracing_on */
*p = !val;
(*ppos)++;
return cnt;
}
static struct file_operations rb_simple_fops = {
.open = tracing_open_generic,
.read = rb_simple_read,
.write = rb_simple_write,
};
static __init int rb_init_debugfs(void)
{
struct dentry *d_tracer;
struct dentry *entry;
d_tracer = tracing_init_dentry();
entry = debugfs_create_file("tracing_on", 0644, d_tracer,
&ring_buffers_off, &rb_simple_fops);
if (!entry)
pr_warning("Could not create debugfs 'tracing_on' entry\n");
return 0;
}
fs_initcall(rb_init_debugfs);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment