Skip to content

Commit

Permalink
ftrace: Allow other users of function tracing to use the output listing
Browse files Browse the repository at this point in the history
The function tracer is set up to allow any other subsystem (like perf)
to use it. Ftrace already has a way to list what functions are enabled
by the global_ops. It would be very helpful to let other users of
the function tracer to be able to use the same code.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Dec 21, 2011
1 parent 06a51d9 commit fc13cb0
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 16 deletions.
35 changes: 35 additions & 0 deletions include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ enum {
FTRACE_UPDATE_MAKE_NOP,
};

enum {
FTRACE_ITER_FILTER = (1 << 0),
FTRACE_ITER_NOTRACE = (1 << 1),
FTRACE_ITER_PRINTALL = (1 << 2),
FTRACE_ITER_HASH = (1 << 3),
FTRACE_ITER_ENABLED = (1 << 4),
};

void arch_ftrace_update_code(int command);

struct ftrace_rec_iter;
Expand All @@ -217,6 +225,15 @@ int ftrace_location(unsigned long ip);

extern ftrace_func_t ftrace_trace_function;

int ftrace_regex_open(struct ftrace_ops *ops, int flag,
struct inode *inode, struct file *file);
ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos);
ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos);
loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int origin);
int ftrace_regex_release(struct inode *inode, struct file *file);

/* defined in arch */
extern int ftrace_ip_converted(unsigned long ip);
extern int ftrace_dyn_arch_init(void *data);
Expand Down Expand Up @@ -311,6 +328,24 @@ static inline int ftrace_text_reserved(void *start, void *end)
{
return 0;
}

/*
* Again users of functions that have ftrace_ops may not
* have them defined when ftrace is not enabled, but these
* functions may still be called. Use a macro instead of inline.
*/
#define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; })

static inline ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos) { return -ENODEV; }
static inline ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos) { return -ENODEV; }
static inline loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
{
return -ENODEV;
}
static inline int
ftrace_regex_release(struct inode *inode, struct file *file) { return -ENODEV; }
#endif /* CONFIG_DYNAMIC_FTRACE */

/* totally disable ftrace - can not re-enable after this */
Expand Down
41 changes: 25 additions & 16 deletions kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -2134,14 +2134,6 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
return 0;
}

enum {
FTRACE_ITER_FILTER = (1 << 0),
FTRACE_ITER_NOTRACE = (1 << 1),
FTRACE_ITER_PRINTALL = (1 << 2),
FTRACE_ITER_HASH = (1 << 3),
FTRACE_ITER_ENABLED = (1 << 4),
};

#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */

struct ftrace_iterator {
Expand Down Expand Up @@ -2249,7 +2241,7 @@ static void *
t_next(struct seq_file *m, void *v, loff_t *pos)
{
struct ftrace_iterator *iter = m->private;
struct ftrace_ops *ops = &global_ops;
struct ftrace_ops *ops = iter->ops;
struct dyn_ftrace *rec = NULL;

if (unlikely(ftrace_disabled))
Expand Down Expand Up @@ -2305,7 +2297,7 @@ static void reset_iter_read(struct ftrace_iterator *iter)
static void *t_start(struct seq_file *m, loff_t *pos)
{
struct ftrace_iterator *iter = m->private;
struct ftrace_ops *ops = &global_ops;
struct ftrace_ops *ops = iter->ops;
void *p = NULL;
loff_t l;

Expand Down Expand Up @@ -2414,6 +2406,7 @@ ftrace_avail_open(struct inode *inode, struct file *file)
return -ENOMEM;

iter->pg = ftrace_pages_start;
iter->ops = &global_ops;

ret = seq_open(file, &show_ftrace_seq_ops);
if (!ret) {
Expand Down Expand Up @@ -2442,6 +2435,7 @@ ftrace_enabled_open(struct inode *inode, struct file *file)

iter->pg = ftrace_pages_start;
iter->flags = FTRACE_ITER_ENABLED;
iter->ops = &global_ops;

ret = seq_open(file, &show_ftrace_seq_ops);
if (!ret) {
Expand All @@ -2462,7 +2456,23 @@ static void ftrace_filter_reset(struct ftrace_hash *hash)
mutex_unlock(&ftrace_lock);
}

static int
/**
* ftrace_regex_open - initialize function tracer filter files
* @ops: The ftrace_ops that hold the hash filters
* @flag: The type of filter to process
* @inode: The inode, usually passed in to your open routine
* @file: The file, usually passed in to your open routine
*
* ftrace_regex_open() initializes the filter files for the
* @ops. Depending on @flag it may process the filter hash or
* the notrace hash of @ops. With this called from the open
* routine, you can use ftrace_filter_write() for the write
* routine if @flag has FTRACE_ITER_FILTER set, or
* ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set.
* ftrace_regex_lseek() should be used as the lseek routine, and
* release must call ftrace_regex_release().
*/
int
ftrace_regex_open(struct ftrace_ops *ops, int flag,
struct inode *inode, struct file *file)
{
Expand Down Expand Up @@ -2542,7 +2552,7 @@ ftrace_notrace_open(struct inode *inode, struct file *file)
inode, file);
}

static loff_t
loff_t
ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
{
loff_t ret;
Expand Down Expand Up @@ -3095,14 +3105,14 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
return ret;
}

static ssize_t
ssize_t
ftrace_filter_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
}

static ssize_t
ssize_t
ftrace_notrace_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
Expand Down Expand Up @@ -3292,8 +3302,7 @@ static void __init set_ftrace_early_filters(void)
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
}

static int
ftrace_regex_release(struct inode *inode, struct file *file)
int ftrace_regex_release(struct inode *inode, struct file *file)
{
struct seq_file *m = (struct seq_file *)file->private_data;
struct ftrace_iterator *iter;
Expand Down

0 comments on commit fc13cb0

Please sign in to comment.