ftrace: Have the cached module list show in set_ftrace_filter

When writing in a module filter into set_ftrace_filter for a module that is
not yet loaded, it it cached, and will be executed when the module is loaded
(although that is not implemented yet at this commit). Display the list of
cached modules to be traced.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
Steven Rostedt (VMware) 2017-06-23 16:05:11 -04:00
parent 673feb9d76
commit 5985ea8bd5
2 changed files with 102 additions and 13 deletions

View File

@ -446,7 +446,8 @@ enum {
FTRACE_ITER_PRINTALL = (1 << 2),
FTRACE_ITER_DO_PROBES = (1 << 3),
FTRACE_ITER_PROBE = (1 << 4),
FTRACE_ITER_ENABLED = (1 << 5),
FTRACE_ITER_MOD = (1 << 5),
FTRACE_ITER_ENABLED = (1 << 6),
};
void arch_ftrace_update_code(int command);

View File

@ -3112,6 +3112,7 @@ ftrace_allocate_pages(unsigned long num_to_init)
struct ftrace_iterator {
loff_t pos;
loff_t func_pos;
loff_t mod_pos;
struct ftrace_page *pg;
struct dyn_ftrace *func;
struct ftrace_func_probe *probe;
@ -3119,6 +3120,8 @@ struct ftrace_iterator {
struct trace_parser parser;
struct ftrace_hash *hash;
struct ftrace_ops *ops;
struct trace_array *tr;
struct list_head *mod_list;
int pidx;
int idx;
unsigned flags;
@ -3203,13 +3206,13 @@ static void *t_probe_start(struct seq_file *m, loff_t *pos)
if (!(iter->flags & FTRACE_ITER_DO_PROBES))
return NULL;
if (iter->func_pos > *pos)
if (iter->mod_pos > *pos)
return NULL;
iter->probe = NULL;
iter->probe_entry = NULL;
iter->pidx = 0;
for (l = 0; l <= (*pos - iter->func_pos); ) {
for (l = 0; l <= (*pos - iter->mod_pos); ) {
p = t_probe_next(m, &l);
if (!p)
break;
@ -3247,6 +3250,82 @@ t_probe_show(struct seq_file *m, struct ftrace_iterator *iter)
return 0;
}
static void *
t_mod_next(struct seq_file *m, loff_t *pos)
{
struct ftrace_iterator *iter = m->private;
struct trace_array *tr = iter->tr;
(*pos)++;
iter->pos = *pos;
iter->mod_list = iter->mod_list->next;
if (iter->mod_list == &tr->mod_trace ||
iter->mod_list == &tr->mod_notrace) {
iter->flags &= ~FTRACE_ITER_MOD;
return NULL;
}
iter->mod_pos = *pos;
return iter;
}
static void *t_mod_start(struct seq_file *m, loff_t *pos)
{
struct ftrace_iterator *iter = m->private;
void *p = NULL;
loff_t l;
if (iter->func_pos > *pos)
return NULL;
iter->mod_pos = iter->func_pos;
/* probes are only available if tr is set */
if (!iter->tr)
return NULL;
for (l = 0; l <= (*pos - iter->func_pos); ) {
p = t_mod_next(m, &l);
if (!p)
break;
}
if (!p) {
iter->flags &= ~FTRACE_ITER_MOD;
return t_probe_start(m, pos);
}
/* Only set this if we have an item */
iter->flags |= FTRACE_ITER_MOD;
return iter;
}
static int
t_mod_show(struct seq_file *m, struct ftrace_iterator *iter)
{
struct ftrace_mod_load *ftrace_mod;
struct trace_array *tr = iter->tr;
if (WARN_ON_ONCE(!iter->mod_list) ||
iter->mod_list == &tr->mod_trace ||
iter->mod_list == &tr->mod_notrace)
return -EIO;
ftrace_mod = list_entry(iter->mod_list, struct ftrace_mod_load, list);
if (ftrace_mod->func)
seq_printf(m, "%s", ftrace_mod->func);
else
seq_putc(m, '*');
seq_printf(m, ":mod:%s\n", ftrace_mod->module);
return 0;
}
static void *
t_func_next(struct seq_file *m, loff_t *pos)
{
@ -3288,7 +3367,7 @@ static void *
t_next(struct seq_file *m, void *v, loff_t *pos)
{
struct ftrace_iterator *iter = m->private;
loff_t l = *pos; /* t_hash_start() must use original pos */
loff_t l = *pos; /* t_probe_start() must use original pos */
void *ret;
if (unlikely(ftrace_disabled))
@ -3297,16 +3376,19 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
if (iter->flags & FTRACE_ITER_PROBE)
return t_probe_next(m, pos);
if (iter->flags & FTRACE_ITER_MOD)
return t_mod_next(m, pos);
if (iter->flags & FTRACE_ITER_PRINTALL) {
/* next must increment pos, and t_probe_start does not */
(*pos)++;
return t_probe_start(m, &l);
return t_mod_start(m, &l);
}
ret = t_func_next(m, pos);
if (!ret)
return t_probe_start(m, &l);
return t_mod_start(m, &l);
return ret;
}
@ -3315,7 +3397,7 @@ static void reset_iter_read(struct ftrace_iterator *iter)
{
iter->pos = 0;
iter->func_pos = 0;
iter->flags &= ~(FTRACE_ITER_PRINTALL | FTRACE_ITER_PROBE);
iter->flags &= ~(FTRACE_ITER_PRINTALL | FTRACE_ITER_PROBE | FTRACE_ITER_MOD);
}
static void *t_start(struct seq_file *m, loff_t *pos)
@ -3344,15 +3426,15 @@ static void *t_start(struct seq_file *m, loff_t *pos)
ftrace_hash_empty(iter->hash)) {
iter->func_pos = 1; /* Account for the message */
if (*pos > 0)
return t_probe_start(m, pos);
return t_mod_start(m, pos);
iter->flags |= FTRACE_ITER_PRINTALL;
/* reset in case of seek/pread */
iter->flags &= ~FTRACE_ITER_PROBE;
return iter;
}
if (iter->flags & FTRACE_ITER_PROBE)
return t_probe_start(m, pos);
if (iter->flags & FTRACE_ITER_MOD)
return t_mod_start(m, pos);
/*
* Unfortunately, we need to restart at ftrace_pages_start
@ -3368,7 +3450,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
}
if (!p)
return t_probe_start(m, pos);
return t_mod_start(m, pos);
return iter;
}
@ -3402,6 +3484,9 @@ static int t_show(struct seq_file *m, void *v)
if (iter->flags & FTRACE_ITER_PROBE)
return t_probe_show(m, iter);
if (iter->flags & FTRACE_ITER_MOD)
return t_mod_show(m, iter);
if (iter->flags & FTRACE_ITER_PRINTALL) {
if (iter->flags & FTRACE_ITER_NOTRACE)
seq_puts(m, "#### no functions disabled ####\n");
@ -3528,17 +3613,20 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
iter->ops = ops;
iter->flags = flag;
iter->tr = tr;
mutex_lock(&ops->func_hash->regex_lock);
if (flag & FTRACE_ITER_NOTRACE) {
hash = ops->func_hash->notrace_hash;
mod_head = tr ? &tr->mod_trace : NULL;
mod_head = tr ? &tr->mod_notrace : NULL;
} else {
hash = ops->func_hash->filter_hash;
mod_head = tr ? &tr->mod_notrace : NULL;
mod_head = tr ? &tr->mod_trace : NULL;
}
iter->mod_list = mod_head;
if (file->f_mode & FMODE_WRITE) {
const int size_bits = FTRACE_HASH_DEFAULT_BITS;