ftrace: Introduce struct ftrace_graph_data

The struct ftrace_graph_data is for generalizing the access to
set_graph_function file.  This is a preparation for adding support to
set_graph_notrace.

Link: http://lkml.kernel.org/r/1381739066-7531-3-git-send-email-namhyung@kernel.org

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
Namhyung Kim 2013-10-14 17:24:24 +09:00 committed by Steven Rostedt
parent 9aa72b4bf8
commit faf982a60f
1 changed files with 62 additions and 19 deletions

View File

@ -3641,7 +3641,7 @@ __setup("ftrace_filter=", set_ftrace_filter);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_FUNCTION_GRAPH_TRACER
static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata; static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); static int ftrace_set_func(unsigned long *array, int *idx, int size, char *buffer);
static int __init set_graph_function(char *str) static int __init set_graph_function(char *str)
{ {
@ -3659,7 +3659,7 @@ static void __init set_ftrace_early_graph(char *buf)
func = strsep(&buf, ","); func = strsep(&buf, ",");
/* we allow only one expression at a time */ /* we allow only one expression at a time */
ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
func); FTRACE_GRAPH_MAX_FUNCS, func);
if (ret) if (ret)
printk(KERN_DEBUG "ftrace: function %s not " printk(KERN_DEBUG "ftrace: function %s not "
"traceable\n", func); "traceable\n", func);
@ -3778,12 +3778,21 @@ static DEFINE_MUTEX(graph_lock);
int ftrace_graph_count; int ftrace_graph_count;
unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
struct ftrace_graph_data {
unsigned long *table;
size_t size;
int *count;
const struct seq_operations *seq_ops;
};
static void * static void *
__g_next(struct seq_file *m, loff_t *pos) __g_next(struct seq_file *m, loff_t *pos)
{ {
if (*pos >= ftrace_graph_count) struct ftrace_graph_data *fgd = m->private;
if (*pos >= *fgd->count)
return NULL; return NULL;
return &ftrace_graph_funcs[*pos]; return &fgd->table[*pos];
} }
static void * static void *
@ -3795,10 +3804,12 @@ g_next(struct seq_file *m, void *v, loff_t *pos)
static void *g_start(struct seq_file *m, loff_t *pos) static void *g_start(struct seq_file *m, loff_t *pos)
{ {
struct ftrace_graph_data *fgd = m->private;
mutex_lock(&graph_lock); mutex_lock(&graph_lock);
/* Nothing, tell g_show to print all functions are enabled */ /* Nothing, tell g_show to print all functions are enabled */
if (!ftrace_graph_count && !*pos) if (!*fgd->count && !*pos)
return (void *)1; return (void *)1;
return __g_next(m, pos); return __g_next(m, pos);
@ -3834,37 +3845,68 @@ static const struct seq_operations ftrace_graph_seq_ops = {
}; };
static int static int
ftrace_graph_open(struct inode *inode, struct file *file) __ftrace_graph_open(struct inode *inode, struct file *file,
struct ftrace_graph_data *fgd)
{ {
int ret = 0; int ret = 0;
if (unlikely(ftrace_disabled))
return -ENODEV;
mutex_lock(&graph_lock); mutex_lock(&graph_lock);
if ((file->f_mode & FMODE_WRITE) && if ((file->f_mode & FMODE_WRITE) &&
(file->f_flags & O_TRUNC)) { (file->f_flags & O_TRUNC)) {
ftrace_graph_count = 0; *fgd->count = 0;
memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs)); memset(fgd->table, 0, fgd->size * sizeof(*fgd->table));
} }
mutex_unlock(&graph_lock); mutex_unlock(&graph_lock);
if (file->f_mode & FMODE_READ) if (file->f_mode & FMODE_READ) {
ret = seq_open(file, &ftrace_graph_seq_ops); ret = seq_open(file, fgd->seq_ops);
if (!ret) {
struct seq_file *m = file->private_data;
m->private = fgd;
}
} else
file->private_data = fgd;
return ret; return ret;
} }
static int
ftrace_graph_open(struct inode *inode, struct file *file)
{
struct ftrace_graph_data *fgd;
if (unlikely(ftrace_disabled))
return -ENODEV;
fgd = kmalloc(sizeof(*fgd), GFP_KERNEL);
if (fgd == NULL)
return -ENOMEM;
fgd->table = ftrace_graph_funcs;
fgd->size = FTRACE_GRAPH_MAX_FUNCS;
fgd->count = &ftrace_graph_count;
fgd->seq_ops = &ftrace_graph_seq_ops;
return __ftrace_graph_open(inode, file, fgd);
}
static int static int
ftrace_graph_release(struct inode *inode, struct file *file) ftrace_graph_release(struct inode *inode, struct file *file)
{ {
if (file->f_mode & FMODE_READ) if (file->f_mode & FMODE_READ) {
struct seq_file *m = file->private_data;
kfree(m->private);
seq_release(inode, file); seq_release(inode, file);
} else {
kfree(file->private_data);
}
return 0; return 0;
} }
static int static int
ftrace_set_func(unsigned long *array, int *idx, char *buffer) ftrace_set_func(unsigned long *array, int *idx, int size, char *buffer)
{ {
struct dyn_ftrace *rec; struct dyn_ftrace *rec;
struct ftrace_page *pg; struct ftrace_page *pg;
@ -3877,7 +3919,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
/* decode regex */ /* decode regex */
type = filter_parse_regex(buffer, strlen(buffer), &search, &not); type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) if (!not && *idx >= size)
return -EBUSY; return -EBUSY;
search_len = strlen(search); search_len = strlen(search);
@ -3905,7 +3947,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
fail = 0; fail = 0;
if (!exists) { if (!exists) {
array[(*idx)++] = rec->ip; array[(*idx)++] = rec->ip;
if (*idx >= FTRACE_GRAPH_MAX_FUNCS) if (*idx >= size)
goto out; goto out;
} }
} else { } else {
@ -3932,6 +3974,7 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
{ {
struct trace_parser parser; struct trace_parser parser;
ssize_t read, ret; ssize_t read, ret;
struct ftrace_graph_data *fgd = file->private_data;
if (!cnt) if (!cnt)
return 0; return 0;
@ -3949,8 +3992,8 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
parser.buffer[parser.idx] = 0; parser.buffer[parser.idx] = 0;
/* we allow only one expression at a time */ /* we allow only one expression at a time */
ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, ret = ftrace_set_func(fgd->table, fgd->count, fgd->size,
parser.buffer); parser.buffer);
if (ret) if (ret)
goto out_free; goto out_free;
} }