aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace.h3
-rw-r--r--kernel/trace/ftrace.c59
2 files changed, 60 insertions, 2 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9962e954a633..3e711122f66c 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -317,6 +317,8 @@ struct dyn_ftrace {
317}; 317};
318 318
319int ftrace_force_update(void); 319int ftrace_force_update(void);
320int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
321 int remove, int reset);
320int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, 322int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
321 int len, int reset); 323 int len, int reset);
322int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, 324int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
@@ -544,6 +546,7 @@ static inline int ftrace_text_reserved(void *start, void *end)
544 */ 546 */
545#define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; }) 547#define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; })
546#define ftrace_set_early_filter(ops, buf, enable) do { } while (0) 548#define ftrace_set_early_filter(ops, buf, enable) do { } while (0)
549#define ftrace_set_filter_ip(ops, ip, remove, reset) ({ -ENODEV; })
547#define ftrace_set_filter(ops, buf, len, reset) ({ -ENODEV; }) 550#define ftrace_set_filter(ops, buf, len, reset) ({ -ENODEV; })
548#define ftrace_set_notrace(ops, buf, len, reset) ({ -ENODEV; }) 551#define ftrace_set_notrace(ops, buf, len, reset) ({ -ENODEV; })
549#define ftrace_free_filter(ops) do { } while (0) 552#define ftrace_free_filter(ops) do { } while (0)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 528d997c7f99..9dcf15d38380 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3242,8 +3242,27 @@ ftrace_notrace_write(struct file *file, const char __user *ubuf,
3242} 3242}
3243 3243
3244static int 3244static int
3245ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, 3245ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
3246 int reset, int enable) 3246{
3247 struct ftrace_func_entry *entry;
3248
3249 if (!ftrace_location(ip))
3250 return -EINVAL;
3251
3252 if (remove) {
3253 entry = ftrace_lookup_ip(hash, ip);
3254 if (!entry)
3255 return -ENOENT;
3256 free_hash_entry(hash, entry);
3257 return 0;
3258 }
3259
3260 return add_hash_entry(hash, ip);
3261}
3262
3263static int
3264ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
3265 unsigned long ip, int remove, int reset, int enable)
3247{ 3266{
3248 struct ftrace_hash **orig_hash; 3267 struct ftrace_hash **orig_hash;
3249 struct ftrace_hash *hash; 3268 struct ftrace_hash *hash;
@@ -3272,6 +3291,11 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
3272 ret = -EINVAL; 3291 ret = -EINVAL;
3273 goto out_regex_unlock; 3292 goto out_regex_unlock;
3274 } 3293 }
3294 if (ip) {
3295 ret = ftrace_match_addr(hash, ip, remove);
3296 if (ret < 0)
3297 goto out_regex_unlock;
3298 }
3275 3299
3276 mutex_lock(&ftrace_lock); 3300 mutex_lock(&ftrace_lock);
3277 ret = ftrace_hash_move(ops, enable, orig_hash, hash); 3301 ret = ftrace_hash_move(ops, enable, orig_hash, hash);
@@ -3288,6 +3312,37 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
3288 return ret; 3312 return ret;
3289} 3313}
3290 3314
3315static int
3316ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove,
3317 int reset, int enable)
3318{
3319 return ftrace_set_hash(ops, 0, 0, ip, remove, reset, enable);
3320}
3321
3322/**
3323 * ftrace_set_filter_ip - set a function to filter on in ftrace by address
3324 * @ops - the ops to set the filter with
3325 * @ip - the address to add to or remove from the filter.
3326 * @remove - non zero to remove the ip from the filter
3327 * @reset - non zero to reset all filters before applying this filter.
3328 *
3329 * Filters denote which functions should be enabled when tracing is enabled
3330 * If @ip is NULL, it failes to update filter.
3331 */
3332int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
3333 int remove, int reset)
3334{
3335 return ftrace_set_addr(ops, ip, remove, reset, 1);
3336}
3337EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
3338
3339static int
3340ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
3341 int reset, int enable)
3342{
3343 return ftrace_set_hash(ops, buf, len, 0, 0, reset, enable);
3344}
3345
3291/** 3346/**
3292 * ftrace_set_filter - set a function to filter on in ftrace 3347 * ftrace_set_filter - set a function to filter on in ftrace
3293 * @ops - the ops to set the filter with 3348 * @ops - the ops to set the filter with