ftrace: Have cached module filters be an active filter

When a module filter is added to set_ftrace_filter, if the module is not
loaded, it is cached. This should be considered an active filter, and
function tracing should be filtered by this. That is, if a cached module
filter is the only filter set, then no function tracing should be happening,
as all the functions available will be filtered out.

This makes sense, as the reason to add a cached module filter, is to trace
the module when you load it. There shouldn't be any other tracing happening
until then.
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent d7fbf8df
...@@ -120,6 +120,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); ...@@ -120,6 +120,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
* this ops will fail to register or set_filter_ip. * this ops will fail to register or set_filter_ip.
* PID - Is affected by set_ftrace_pid (allows filtering on those pids) * PID - Is affected by set_ftrace_pid (allows filtering on those pids)
* RCU - Set when the ops can only be called when RCU is watching. * RCU - Set when the ops can only be called when RCU is watching.
* TRACE_ARRAY - The ops->private points to a trace_array descriptor.
*/ */
enum { enum {
FTRACE_OPS_FL_ENABLED = 1 << 0, FTRACE_OPS_FL_ENABLED = 1 << 0,
...@@ -138,6 +139,7 @@ enum { ...@@ -138,6 +139,7 @@ enum {
FTRACE_OPS_FL_IPMODIFY = 1 << 13, FTRACE_OPS_FL_IPMODIFY = 1 << 13,
FTRACE_OPS_FL_PID = 1 << 14, FTRACE_OPS_FL_PID = 1 << 14,
FTRACE_OPS_FL_RCU = 1 << 15, FTRACE_OPS_FL_RCU = 1 << 15,
FTRACE_OPS_FL_TRACE_ARRAY = 1 << 16,
}; };
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
......
...@@ -1410,6 +1410,9 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash) ...@@ -1410,6 +1410,9 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
if (!new_hash) if (!new_hash)
return NULL; return NULL;
if (hash)
new_hash->flags = hash->flags;
/* Empty hash? */ /* Empty hash? */
if (ftrace_hash_empty(hash)) if (ftrace_hash_empty(hash))
return new_hash; return new_hash;
...@@ -1454,7 +1457,7 @@ __ftrace_hash_move(struct ftrace_hash *src) ...@@ -1454,7 +1457,7 @@ __ftrace_hash_move(struct ftrace_hash *src)
/* /*
* If the new source is empty, just return the empty_hash. * If the new source is empty, just return the empty_hash.
*/ */
if (!src->count) if (ftrace_hash_empty(src))
return EMPTY_HASH; return EMPTY_HASH;
/* /*
...@@ -1471,6 +1474,8 @@ __ftrace_hash_move(struct ftrace_hash *src) ...@@ -1471,6 +1474,8 @@ __ftrace_hash_move(struct ftrace_hash *src)
if (!new_hash) if (!new_hash)
return NULL; return NULL;
new_hash->flags = src->flags;
size = 1 << src->size_bits; size = 1 << src->size_bits;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
hhd = &src->buckets[i]; hhd = &src->buckets[i];
...@@ -1701,7 +1706,7 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops, ...@@ -1701,7 +1706,7 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
struct dyn_ftrace *rec; struct dyn_ftrace *rec;
bool update = false; bool update = false;
int count = 0; int count = 0;
int all = 0; int all = false;
/* Only update if the ops has been registered */ /* Only update if the ops has been registered */
if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
...@@ -1722,7 +1727,7 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops, ...@@ -1722,7 +1727,7 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
hash = ops->func_hash->filter_hash; hash = ops->func_hash->filter_hash;
other_hash = ops->func_hash->notrace_hash; other_hash = ops->func_hash->notrace_hash;
if (ftrace_hash_empty(hash)) if (ftrace_hash_empty(hash))
all = 1; all = true;
} else { } else {
inc = !inc; inc = !inc;
hash = ops->func_hash->notrace_hash; hash = ops->func_hash->notrace_hash;
...@@ -4028,6 +4033,9 @@ static void process_mod_list(struct list_head *head, struct ftrace_ops *ops, ...@@ -4028,6 +4033,9 @@ static void process_mod_list(struct list_head *head, struct ftrace_ops *ops,
free_ftrace_mod(ftrace_mod); free_ftrace_mod(ftrace_mod);
} }
if (enable && list_empty(head))
new_hash->flags &= ~FTRACE_HASH_FL_MOD;
mutex_lock(&ftrace_lock); mutex_lock(&ftrace_lock);
ret = ftrace_hash_move_and_update_ops(ops, orig_hash, ret = ftrace_hash_move_and_update_ops(ops, orig_hash,
...@@ -5035,9 +5043,11 @@ int ftrace_regex_release(struct inode *inode, struct file *file) ...@@ -5035,9 +5043,11 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE) { if (file->f_mode & FMODE_WRITE) {
filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); filter_hash = !!(iter->flags & FTRACE_ITER_FILTER);
if (filter_hash) if (filter_hash) {
orig_hash = &iter->ops->func_hash->filter_hash; orig_hash = &iter->ops->func_hash->filter_hash;
else if (!list_empty(&iter->tr->mod_trace))
iter->hash->flags |= FTRACE_HASH_FL_MOD;
} else
orig_hash = &iter->ops->func_hash->notrace_hash; orig_hash = &iter->ops->func_hash->notrace_hash;
mutex_lock(&ftrace_lock); mutex_lock(&ftrace_lock);
......
...@@ -773,10 +773,15 @@ struct ftrace_mod_load { ...@@ -773,10 +773,15 @@ struct ftrace_mod_load {
int enable; int enable;
}; };
enum {
FTRACE_HASH_FL_MOD = (1 << 0),
};
struct ftrace_hash { struct ftrace_hash {
unsigned long size_bits; unsigned long size_bits;
struct hlist_head *buckets; struct hlist_head *buckets;
unsigned long count; unsigned long count;
unsigned long flags;
struct rcu_head rcu; struct rcu_head rcu;
}; };
...@@ -785,7 +790,7 @@ ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip); ...@@ -785,7 +790,7 @@ ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip);
static __always_inline bool ftrace_hash_empty(struct ftrace_hash *hash) static __always_inline bool ftrace_hash_empty(struct ftrace_hash *hash)
{ {
return !hash || !hash->count; return !hash || !(hash->count || (hash->flags & FTRACE_HASH_FL_MOD));
} }
/* Standard output formatting function used for function return traces */ /* Standard output formatting function used for function return traces */
......
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