diff options
| -rw-r--r-- | include/linux/ftrace.h | 4 | ||||
| -rw-r--r-- | include/linux/ftrace_event.h | 1 | ||||
| -rw-r--r-- | kernel/trace/Kconfig | 2 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 126 | ||||
| -rw-r--r-- | kernel/trace/trace_events.c | 54 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 289 |
6 files changed, 368 insertions, 108 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index f83e17a40e8b..99d0fbcbaf79 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
| @@ -90,6 +90,8 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip, | |||
| 90 | * not set this, then the ftrace infrastructure will add recursion | 90 | * not set this, then the ftrace infrastructure will add recursion |
| 91 | * protection for the caller. | 91 | * protection for the caller. |
| 92 | * STUB - The ftrace_ops is just a place holder. | 92 | * STUB - The ftrace_ops is just a place holder. |
| 93 | * INITIALIZED - The ftrace_ops has already been initialized (first use time | ||
| 94 | * register_ftrace_function() is called, it will initialized the ops) | ||
| 93 | */ | 95 | */ |
| 94 | enum { | 96 | enum { |
| 95 | FTRACE_OPS_FL_ENABLED = 1 << 0, | 97 | FTRACE_OPS_FL_ENABLED = 1 << 0, |
| @@ -100,6 +102,7 @@ enum { | |||
| 100 | FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5, | 102 | FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5, |
| 101 | FTRACE_OPS_FL_RECURSION_SAFE = 1 << 6, | 103 | FTRACE_OPS_FL_RECURSION_SAFE = 1 << 6, |
| 102 | FTRACE_OPS_FL_STUB = 1 << 7, | 104 | FTRACE_OPS_FL_STUB = 1 << 7, |
| 105 | FTRACE_OPS_FL_INITIALIZED = 1 << 8, | ||
| 103 | }; | 106 | }; |
| 104 | 107 | ||
| 105 | struct ftrace_ops { | 108 | struct ftrace_ops { |
| @@ -110,6 +113,7 @@ struct ftrace_ops { | |||
| 110 | #ifdef CONFIG_DYNAMIC_FTRACE | 113 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 111 | struct ftrace_hash *notrace_hash; | 114 | struct ftrace_hash *notrace_hash; |
| 112 | struct ftrace_hash *filter_hash; | 115 | struct ftrace_hash *filter_hash; |
| 116 | struct mutex regex_lock; | ||
| 113 | #endif | 117 | #endif |
| 114 | }; | 118 | }; |
| 115 | 119 | ||
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 34e00fb49bec..4372658c73ae 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h | |||
| @@ -293,6 +293,7 @@ struct ftrace_event_file { | |||
| 293 | * caching and such. Which is mostly OK ;-) | 293 | * caching and such. Which is mostly OK ;-) |
| 294 | */ | 294 | */ |
| 295 | unsigned long flags; | 295 | unsigned long flags; |
| 296 | atomic_t sm_ref; /* soft-mode reference counter */ | ||
| 296 | }; | 297 | }; |
| 297 | 298 | ||
| 298 | #define __TRACE_EVENT_FLAGS(name, value) \ | 299 | #define __TRACE_EVENT_FLAGS(name, value) \ |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 5e9efd4b83a4..015f85aaca08 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
| @@ -71,6 +71,7 @@ config TRACE_CLOCK | |||
| 71 | config RING_BUFFER | 71 | config RING_BUFFER |
| 72 | bool | 72 | bool |
| 73 | select TRACE_CLOCK | 73 | select TRACE_CLOCK |
| 74 | select IRQ_WORK | ||
| 74 | 75 | ||
| 75 | config FTRACE_NMI_ENTER | 76 | config FTRACE_NMI_ENTER |
| 76 | bool | 77 | bool |
| @@ -107,7 +108,6 @@ config TRACING | |||
| 107 | select BINARY_PRINTF | 108 | select BINARY_PRINTF |
| 108 | select EVENT_TRACING | 109 | select EVENT_TRACING |
| 109 | select TRACE_CLOCK | 110 | select TRACE_CLOCK |
| 110 | select IRQ_WORK | ||
| 111 | 111 | ||
| 112 | config GENERIC_TRACER | 112 | config GENERIC_TRACER |
| 113 | bool | 113 | bool |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8a5c017bb50c..b549b0f5b977 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -64,6 +64,13 @@ | |||
| 64 | 64 | ||
| 65 | #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL) | 65 | #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL) |
| 66 | 66 | ||
| 67 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 68 | #define INIT_REGEX_LOCK(opsname) \ | ||
| 69 | .regex_lock = __MUTEX_INITIALIZER(opsname.regex_lock), | ||
| 70 | #else | ||
| 71 | #define INIT_REGEX_LOCK(opsname) | ||
| 72 | #endif | ||
| 73 | |||
| 67 | static struct ftrace_ops ftrace_list_end __read_mostly = { | 74 | static struct ftrace_ops ftrace_list_end __read_mostly = { |
| 68 | .func = ftrace_stub, | 75 | .func = ftrace_stub, |
| 69 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB, | 76 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB, |
| @@ -131,6 +138,16 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip); | |||
| 131 | while (likely(op = rcu_dereference_raw((op)->next)) && \ | 138 | while (likely(op = rcu_dereference_raw((op)->next)) && \ |
| 132 | unlikely((op) != &ftrace_list_end)) | 139 | unlikely((op) != &ftrace_list_end)) |
| 133 | 140 | ||
| 141 | static inline void ftrace_ops_init(struct ftrace_ops *ops) | ||
| 142 | { | ||
| 143 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 144 | if (!(ops->flags & FTRACE_OPS_FL_INITIALIZED)) { | ||
| 145 | mutex_init(&ops->regex_lock); | ||
| 146 | ops->flags |= FTRACE_OPS_FL_INITIALIZED; | ||
| 147 | } | ||
| 148 | #endif | ||
| 149 | } | ||
| 150 | |||
| 134 | /** | 151 | /** |
| 135 | * ftrace_nr_registered_ops - return number of ops registered | 152 | * ftrace_nr_registered_ops - return number of ops registered |
| 136 | * | 153 | * |
| @@ -907,7 +924,8 @@ static void unregister_ftrace_profiler(void) | |||
| 907 | #else | 924 | #else |
| 908 | static struct ftrace_ops ftrace_profile_ops __read_mostly = { | 925 | static struct ftrace_ops ftrace_profile_ops __read_mostly = { |
| 909 | .func = function_profile_call, | 926 | .func = function_profile_call, |
| 910 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 927 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 928 | INIT_REGEX_LOCK(ftrace_profile_ops) | ||
| 911 | }; | 929 | }; |
| 912 | 930 | ||
| 913 | static int register_ftrace_profiler(void) | 931 | static int register_ftrace_profiler(void) |
| @@ -1103,11 +1121,10 @@ static struct ftrace_ops global_ops = { | |||
| 1103 | .func = ftrace_stub, | 1121 | .func = ftrace_stub, |
| 1104 | .notrace_hash = EMPTY_HASH, | 1122 | .notrace_hash = EMPTY_HASH, |
| 1105 | .filter_hash = EMPTY_HASH, | 1123 | .filter_hash = EMPTY_HASH, |
| 1106 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 1124 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 1125 | INIT_REGEX_LOCK(global_ops) | ||
| 1107 | }; | 1126 | }; |
| 1108 | 1127 | ||
| 1109 | static DEFINE_MUTEX(ftrace_regex_lock); | ||
| 1110 | |||
| 1111 | struct ftrace_page { | 1128 | struct ftrace_page { |
| 1112 | struct ftrace_page *next; | 1129 | struct ftrace_page *next; |
| 1113 | struct dyn_ftrace *records; | 1130 | struct dyn_ftrace *records; |
| @@ -1247,6 +1264,7 @@ static void free_ftrace_hash_rcu(struct ftrace_hash *hash) | |||
| 1247 | 1264 | ||
| 1248 | void ftrace_free_filter(struct ftrace_ops *ops) | 1265 | void ftrace_free_filter(struct ftrace_ops *ops) |
| 1249 | { | 1266 | { |
| 1267 | ftrace_ops_init(ops); | ||
| 1250 | free_ftrace_hash(ops->filter_hash); | 1268 | free_ftrace_hash(ops->filter_hash); |
| 1251 | free_ftrace_hash(ops->notrace_hash); | 1269 | free_ftrace_hash(ops->notrace_hash); |
| 1252 | } | 1270 | } |
| @@ -2441,7 +2459,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 2441 | !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) || | 2459 | !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) || |
| 2442 | 2460 | ||
| 2443 | ((iter->flags & FTRACE_ITER_ENABLED) && | 2461 | ((iter->flags & FTRACE_ITER_ENABLED) && |
| 2444 | !(rec->flags & ~FTRACE_FL_MASK))) { | 2462 | !(rec->flags & FTRACE_FL_ENABLED))) { |
| 2445 | 2463 | ||
| 2446 | rec = NULL; | 2464 | rec = NULL; |
| 2447 | goto retry; | 2465 | goto retry; |
| @@ -2624,6 +2642,8 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
| 2624 | struct ftrace_hash *hash; | 2642 | struct ftrace_hash *hash; |
| 2625 | int ret = 0; | 2643 | int ret = 0; |
| 2626 | 2644 | ||
| 2645 | ftrace_ops_init(ops); | ||
| 2646 | |||
| 2627 | if (unlikely(ftrace_disabled)) | 2647 | if (unlikely(ftrace_disabled)) |
| 2628 | return -ENODEV; | 2648 | return -ENODEV; |
| 2629 | 2649 | ||
| @@ -2636,28 +2656,26 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
| 2636 | return -ENOMEM; | 2656 | return -ENOMEM; |
| 2637 | } | 2657 | } |
| 2638 | 2658 | ||
| 2659 | iter->ops = ops; | ||
| 2660 | iter->flags = flag; | ||
| 2661 | |||
| 2662 | mutex_lock(&ops->regex_lock); | ||
| 2663 | |||
| 2639 | if (flag & FTRACE_ITER_NOTRACE) | 2664 | if (flag & FTRACE_ITER_NOTRACE) |
| 2640 | hash = ops->notrace_hash; | 2665 | hash = ops->notrace_hash; |
| 2641 | else | 2666 | else |
| 2642 | hash = ops->filter_hash; | 2667 | hash = ops->filter_hash; |
| 2643 | 2668 | ||
| 2644 | iter->ops = ops; | ||
| 2645 | iter->flags = flag; | ||
| 2646 | |||
| 2647 | if (file->f_mode & FMODE_WRITE) { | 2669 | if (file->f_mode & FMODE_WRITE) { |
| 2648 | mutex_lock(&ftrace_lock); | ||
| 2649 | iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); | 2670 | iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); |
| 2650 | mutex_unlock(&ftrace_lock); | ||
| 2651 | |||
| 2652 | if (!iter->hash) { | 2671 | if (!iter->hash) { |
| 2653 | trace_parser_put(&iter->parser); | 2672 | trace_parser_put(&iter->parser); |
| 2654 | kfree(iter); | 2673 | kfree(iter); |
| 2655 | return -ENOMEM; | 2674 | ret = -ENOMEM; |
| 2675 | goto out_unlock; | ||
| 2656 | } | 2676 | } |
| 2657 | } | 2677 | } |
| 2658 | 2678 | ||
| 2659 | mutex_lock(&ftrace_regex_lock); | ||
| 2660 | |||
| 2661 | if ((file->f_mode & FMODE_WRITE) && | 2679 | if ((file->f_mode & FMODE_WRITE) && |
| 2662 | (file->f_flags & O_TRUNC)) | 2680 | (file->f_flags & O_TRUNC)) |
| 2663 | ftrace_filter_reset(iter->hash); | 2681 | ftrace_filter_reset(iter->hash); |
| @@ -2677,7 +2695,9 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
| 2677 | } | 2695 | } |
| 2678 | } else | 2696 | } else |
| 2679 | file->private_data = iter; | 2697 | file->private_data = iter; |
| 2680 | mutex_unlock(&ftrace_regex_lock); | 2698 | |
| 2699 | out_unlock: | ||
| 2700 | mutex_unlock(&ops->regex_lock); | ||
| 2681 | 2701 | ||
| 2682 | return ret; | 2702 | return ret; |
| 2683 | } | 2703 | } |
| @@ -2910,6 +2930,8 @@ static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip, | |||
| 2910 | static struct ftrace_ops trace_probe_ops __read_mostly = | 2930 | static struct ftrace_ops trace_probe_ops __read_mostly = |
| 2911 | { | 2931 | { |
| 2912 | .func = function_trace_probe_call, | 2932 | .func = function_trace_probe_call, |
| 2933 | .flags = FTRACE_OPS_FL_INITIALIZED, | ||
| 2934 | INIT_REGEX_LOCK(trace_probe_ops) | ||
| 2913 | }; | 2935 | }; |
| 2914 | 2936 | ||
| 2915 | static int ftrace_probe_registered; | 2937 | static int ftrace_probe_registered; |
| @@ -2919,8 +2941,12 @@ static void __enable_ftrace_function_probe(void) | |||
| 2919 | int ret; | 2941 | int ret; |
| 2920 | int i; | 2942 | int i; |
| 2921 | 2943 | ||
| 2922 | if (ftrace_probe_registered) | 2944 | if (ftrace_probe_registered) { |
| 2945 | /* still need to update the function call sites */ | ||
| 2946 | if (ftrace_enabled) | ||
| 2947 | ftrace_run_update_code(FTRACE_UPDATE_CALLS); | ||
| 2923 | return; | 2948 | return; |
| 2949 | } | ||
| 2924 | 2950 | ||
| 2925 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { | 2951 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { |
| 2926 | struct hlist_head *hhd = &ftrace_func_hash[i]; | 2952 | struct hlist_head *hhd = &ftrace_func_hash[i]; |
| @@ -2990,19 +3016,21 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 2990 | if (WARN_ON(not)) | 3016 | if (WARN_ON(not)) |
| 2991 | return -EINVAL; | 3017 | return -EINVAL; |
| 2992 | 3018 | ||
| 2993 | mutex_lock(&ftrace_lock); | 3019 | mutex_lock(&trace_probe_ops.regex_lock); |
| 2994 | 3020 | ||
| 2995 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); | 3021 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); |
| 2996 | if (!hash) { | 3022 | if (!hash) { |
| 2997 | count = -ENOMEM; | 3023 | count = -ENOMEM; |
| 2998 | goto out_unlock; | 3024 | goto out; |
| 2999 | } | 3025 | } |
| 3000 | 3026 | ||
| 3001 | if (unlikely(ftrace_disabled)) { | 3027 | if (unlikely(ftrace_disabled)) { |
| 3002 | count = -ENODEV; | 3028 | count = -ENODEV; |
| 3003 | goto out_unlock; | 3029 | goto out; |
| 3004 | } | 3030 | } |
| 3005 | 3031 | ||
| 3032 | mutex_lock(&ftrace_lock); | ||
| 3033 | |||
| 3006 | do_for_each_ftrace_rec(pg, rec) { | 3034 | do_for_each_ftrace_rec(pg, rec) { |
| 3007 | 3035 | ||
| 3008 | if (!ftrace_match_record(rec, NULL, search, len, type)) | 3036 | if (!ftrace_match_record(rec, NULL, search, len, type)) |
| @@ -3056,6 +3084,8 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3056 | 3084 | ||
| 3057 | out_unlock: | 3085 | out_unlock: |
| 3058 | mutex_unlock(&ftrace_lock); | 3086 | mutex_unlock(&ftrace_lock); |
| 3087 | out: | ||
| 3088 | mutex_unlock(&trace_probe_ops.regex_lock); | ||
| 3059 | free_ftrace_hash(hash); | 3089 | free_ftrace_hash(hash); |
| 3060 | 3090 | ||
| 3061 | return count; | 3091 | return count; |
| @@ -3095,7 +3125,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3095 | return; | 3125 | return; |
| 3096 | } | 3126 | } |
| 3097 | 3127 | ||
| 3098 | mutex_lock(&ftrace_lock); | 3128 | mutex_lock(&trace_probe_ops.regex_lock); |
| 3099 | 3129 | ||
| 3100 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); | 3130 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); |
| 3101 | if (!hash) | 3131 | if (!hash) |
| @@ -3133,6 +3163,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3133 | list_add(&entry->free_list, &free_list); | 3163 | list_add(&entry->free_list, &free_list); |
| 3134 | } | 3164 | } |
| 3135 | } | 3165 | } |
| 3166 | mutex_lock(&ftrace_lock); | ||
| 3136 | __disable_ftrace_function_probe(); | 3167 | __disable_ftrace_function_probe(); |
| 3137 | /* | 3168 | /* |
| 3138 | * Remove after the disable is called. Otherwise, if the last | 3169 | * Remove after the disable is called. Otherwise, if the last |
| @@ -3144,9 +3175,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3144 | list_del(&entry->free_list); | 3175 | list_del(&entry->free_list); |
| 3145 | ftrace_free_entry(entry); | 3176 | ftrace_free_entry(entry); |
| 3146 | } | 3177 | } |
| 3178 | mutex_unlock(&ftrace_lock); | ||
| 3147 | 3179 | ||
| 3148 | out_unlock: | 3180 | out_unlock: |
| 3149 | mutex_unlock(&ftrace_lock); | 3181 | mutex_unlock(&trace_probe_ops.regex_lock); |
| 3150 | free_ftrace_hash(hash); | 3182 | free_ftrace_hash(hash); |
| 3151 | } | 3183 | } |
| 3152 | 3184 | ||
| @@ -3256,18 +3288,17 @@ ftrace_regex_write(struct file *file, const char __user *ubuf, | |||
| 3256 | if (!cnt) | 3288 | if (!cnt) |
| 3257 | return 0; | 3289 | return 0; |
| 3258 | 3290 | ||
| 3259 | mutex_lock(&ftrace_regex_lock); | ||
| 3260 | |||
| 3261 | ret = -ENODEV; | ||
| 3262 | if (unlikely(ftrace_disabled)) | ||
| 3263 | goto out_unlock; | ||
| 3264 | |||
| 3265 | if (file->f_mode & FMODE_READ) { | 3291 | if (file->f_mode & FMODE_READ) { |
| 3266 | struct seq_file *m = file->private_data; | 3292 | struct seq_file *m = file->private_data; |
| 3267 | iter = m->private; | 3293 | iter = m->private; |
| 3268 | } else | 3294 | } else |
| 3269 | iter = file->private_data; | 3295 | iter = file->private_data; |
| 3270 | 3296 | ||
| 3297 | if (unlikely(ftrace_disabled)) | ||
| 3298 | return -ENODEV; | ||
| 3299 | |||
| 3300 | /* iter->hash is a local copy, so we don't need regex_lock */ | ||
| 3301 | |||
| 3271 | parser = &iter->parser; | 3302 | parser = &iter->parser; |
| 3272 | read = trace_get_user(parser, ubuf, cnt, ppos); | 3303 | read = trace_get_user(parser, ubuf, cnt, ppos); |
| 3273 | 3304 | ||
| @@ -3276,14 +3307,12 @@ ftrace_regex_write(struct file *file, const char __user *ubuf, | |||
| 3276 | ret = ftrace_process_regex(iter->hash, parser->buffer, | 3307 | ret = ftrace_process_regex(iter->hash, parser->buffer, |
| 3277 | parser->idx, enable); | 3308 | parser->idx, enable); |
| 3278 | trace_parser_clear(parser); | 3309 | trace_parser_clear(parser); |
| 3279 | if (ret) | 3310 | if (ret < 0) |
| 3280 | goto out_unlock; | 3311 | goto out; |
| 3281 | } | 3312 | } |
| 3282 | 3313 | ||
| 3283 | ret = read; | 3314 | ret = read; |
| 3284 | out_unlock: | 3315 | out: |
| 3285 | mutex_unlock(&ftrace_regex_lock); | ||
| 3286 | |||
| 3287 | return ret; | 3316 | return ret; |
| 3288 | } | 3317 | } |
| 3289 | 3318 | ||
| @@ -3335,16 +3364,19 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, | |||
| 3335 | if (unlikely(ftrace_disabled)) | 3364 | if (unlikely(ftrace_disabled)) |
| 3336 | return -ENODEV; | 3365 | return -ENODEV; |
| 3337 | 3366 | ||
| 3367 | mutex_lock(&ops->regex_lock); | ||
| 3368 | |||
| 3338 | if (enable) | 3369 | if (enable) |
| 3339 | orig_hash = &ops->filter_hash; | 3370 | orig_hash = &ops->filter_hash; |
| 3340 | else | 3371 | else |
| 3341 | orig_hash = &ops->notrace_hash; | 3372 | orig_hash = &ops->notrace_hash; |
| 3342 | 3373 | ||
| 3343 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); | 3374 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); |
| 3344 | if (!hash) | 3375 | if (!hash) { |
| 3345 | return -ENOMEM; | 3376 | ret = -ENOMEM; |
| 3377 | goto out_regex_unlock; | ||
| 3378 | } | ||
| 3346 | 3379 | ||
| 3347 | mutex_lock(&ftrace_regex_lock); | ||
| 3348 | if (reset) | 3380 | if (reset) |
| 3349 | ftrace_filter_reset(hash); | 3381 | ftrace_filter_reset(hash); |
| 3350 | if (buf && !ftrace_match_records(hash, buf, len)) { | 3382 | if (buf && !ftrace_match_records(hash, buf, len)) { |
| @@ -3366,7 +3398,7 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, | |||
| 3366 | mutex_unlock(&ftrace_lock); | 3398 | mutex_unlock(&ftrace_lock); |
| 3367 | 3399 | ||
| 3368 | out_regex_unlock: | 3400 | out_regex_unlock: |
| 3369 | mutex_unlock(&ftrace_regex_lock); | 3401 | mutex_unlock(&ops->regex_lock); |
| 3370 | 3402 | ||
| 3371 | free_ftrace_hash(hash); | 3403 | free_ftrace_hash(hash); |
| 3372 | return ret; | 3404 | return ret; |
| @@ -3392,6 +3424,7 @@ ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove, | |||
| 3392 | int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip, | 3424 | int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip, |
| 3393 | int remove, int reset) | 3425 | int remove, int reset) |
| 3394 | { | 3426 | { |
| 3427 | ftrace_ops_init(ops); | ||
| 3395 | return ftrace_set_addr(ops, ip, remove, reset, 1); | 3428 | return ftrace_set_addr(ops, ip, remove, reset, 1); |
| 3396 | } | 3429 | } |
| 3397 | EXPORT_SYMBOL_GPL(ftrace_set_filter_ip); | 3430 | EXPORT_SYMBOL_GPL(ftrace_set_filter_ip); |
| @@ -3416,6 +3449,7 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, | |||
| 3416 | int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, | 3449 | int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, |
| 3417 | int len, int reset) | 3450 | int len, int reset) |
| 3418 | { | 3451 | { |
| 3452 | ftrace_ops_init(ops); | ||
| 3419 | return ftrace_set_regex(ops, buf, len, reset, 1); | 3453 | return ftrace_set_regex(ops, buf, len, reset, 1); |
| 3420 | } | 3454 | } |
| 3421 | EXPORT_SYMBOL_GPL(ftrace_set_filter); | 3455 | EXPORT_SYMBOL_GPL(ftrace_set_filter); |
| @@ -3434,6 +3468,7 @@ EXPORT_SYMBOL_GPL(ftrace_set_filter); | |||
| 3434 | int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, | 3468 | int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, |
| 3435 | int len, int reset) | 3469 | int len, int reset) |
| 3436 | { | 3470 | { |
| 3471 | ftrace_ops_init(ops); | ||
| 3437 | return ftrace_set_regex(ops, buf, len, reset, 0); | 3472 | return ftrace_set_regex(ops, buf, len, reset, 0); |
| 3438 | } | 3473 | } |
| 3439 | EXPORT_SYMBOL_GPL(ftrace_set_notrace); | 3474 | EXPORT_SYMBOL_GPL(ftrace_set_notrace); |
| @@ -3524,6 +3559,8 @@ ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable) | |||
| 3524 | { | 3559 | { |
| 3525 | char *func; | 3560 | char *func; |
| 3526 | 3561 | ||
| 3562 | ftrace_ops_init(ops); | ||
| 3563 | |||
| 3527 | while (buf) { | 3564 | while (buf) { |
| 3528 | func = strsep(&buf, ","); | 3565 | func = strsep(&buf, ","); |
| 3529 | ftrace_set_regex(ops, func, strlen(func), 0, enable); | 3566 | ftrace_set_regex(ops, func, strlen(func), 0, enable); |
| @@ -3551,10 +3588,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 3551 | int filter_hash; | 3588 | int filter_hash; |
| 3552 | int ret; | 3589 | int ret; |
| 3553 | 3590 | ||
| 3554 | mutex_lock(&ftrace_regex_lock); | ||
| 3555 | if (file->f_mode & FMODE_READ) { | 3591 | if (file->f_mode & FMODE_READ) { |
| 3556 | iter = m->private; | 3592 | iter = m->private; |
| 3557 | |||
| 3558 | seq_release(inode, file); | 3593 | seq_release(inode, file); |
| 3559 | } else | 3594 | } else |
| 3560 | iter = file->private_data; | 3595 | iter = file->private_data; |
| @@ -3567,6 +3602,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 3567 | 3602 | ||
| 3568 | trace_parser_put(parser); | 3603 | trace_parser_put(parser); |
| 3569 | 3604 | ||
| 3605 | mutex_lock(&iter->ops->regex_lock); | ||
| 3606 | |||
| 3570 | if (file->f_mode & FMODE_WRITE) { | 3607 | if (file->f_mode & FMODE_WRITE) { |
| 3571 | filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); | 3608 | filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); |
| 3572 | 3609 | ||
| @@ -3584,10 +3621,11 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 3584 | 3621 | ||
| 3585 | mutex_unlock(&ftrace_lock); | 3622 | mutex_unlock(&ftrace_lock); |
| 3586 | } | 3623 | } |
| 3624 | |||
| 3625 | mutex_unlock(&iter->ops->regex_lock); | ||
| 3587 | free_ftrace_hash(iter->hash); | 3626 | free_ftrace_hash(iter->hash); |
| 3588 | kfree(iter); | 3627 | kfree(iter); |
| 3589 | 3628 | ||
| 3590 | mutex_unlock(&ftrace_regex_lock); | ||
| 3591 | return 0; | 3629 | return 0; |
| 3592 | } | 3630 | } |
| 3593 | 3631 | ||
| @@ -4126,7 +4164,8 @@ void __init ftrace_init(void) | |||
| 4126 | 4164 | ||
| 4127 | static struct ftrace_ops global_ops = { | 4165 | static struct ftrace_ops global_ops = { |
| 4128 | .func = ftrace_stub, | 4166 | .func = ftrace_stub, |
| 4129 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 4167 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 4168 | INIT_REGEX_LOCK(global_ops) | ||
| 4130 | }; | 4169 | }; |
| 4131 | 4170 | ||
| 4132 | static int __init ftrace_nodyn_init(void) | 4171 | static int __init ftrace_nodyn_init(void) |
| @@ -4180,8 +4219,9 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip, | |||
| 4180 | } | 4219 | } |
| 4181 | 4220 | ||
| 4182 | static struct ftrace_ops control_ops = { | 4221 | static struct ftrace_ops control_ops = { |
| 4183 | .func = ftrace_ops_control_func, | 4222 | .func = ftrace_ops_control_func, |
| 4184 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 4223 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 4224 | INIT_REGEX_LOCK(control_ops) | ||
| 4185 | }; | 4225 | }; |
| 4186 | 4226 | ||
| 4187 | static inline void | 4227 | static inline void |
| @@ -4539,6 +4579,8 @@ int register_ftrace_function(struct ftrace_ops *ops) | |||
| 4539 | { | 4579 | { |
| 4540 | int ret = -1; | 4580 | int ret = -1; |
| 4541 | 4581 | ||
| 4582 | ftrace_ops_init(ops); | ||
| 4583 | |||
| 4542 | mutex_lock(&ftrace_lock); | 4584 | mutex_lock(&ftrace_lock); |
| 4543 | 4585 | ||
| 4544 | ret = __register_ftrace_function(ops); | 4586 | ret = __register_ftrace_function(ops); |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 53582e982e51..7a0cf68027cc 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -251,7 +251,8 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
| 251 | switch (enable) { | 251 | switch (enable) { |
| 252 | case 0: | 252 | case 0: |
| 253 | /* | 253 | /* |
| 254 | * When soft_disable is set and enable is cleared, we want | 254 | * When soft_disable is set and enable is cleared, the sm_ref |
| 255 | * reference counter is decremented. If it reaches 0, we want | ||
| 255 | * to clear the SOFT_DISABLED flag but leave the event in the | 256 | * to clear the SOFT_DISABLED flag but leave the event in the |
| 256 | * state that it was. That is, if the event was enabled and | 257 | * state that it was. That is, if the event was enabled and |
| 257 | * SOFT_DISABLED isn't set, then do nothing. But if SOFT_DISABLED | 258 | * SOFT_DISABLED isn't set, then do nothing. But if SOFT_DISABLED |
| @@ -263,6 +264,8 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
| 263 | * "soft enable"s (clearing the SOFT_DISABLED bit) wont work. | 264 | * "soft enable"s (clearing the SOFT_DISABLED bit) wont work. |
| 264 | */ | 265 | */ |
| 265 | if (soft_disable) { | 266 | if (soft_disable) { |
| 267 | if (atomic_dec_return(&file->sm_ref) > 0) | ||
| 268 | break; | ||
| 266 | disable = file->flags & FTRACE_EVENT_FL_SOFT_DISABLED; | 269 | disable = file->flags & FTRACE_EVENT_FL_SOFT_DISABLED; |
| 267 | clear_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); | 270 | clear_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); |
| 268 | } else | 271 | } else |
| @@ -291,8 +294,11 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
| 291 | */ | 294 | */ |
| 292 | if (!soft_disable) | 295 | if (!soft_disable) |
| 293 | clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags); | 296 | clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags); |
| 294 | else | 297 | else { |
| 298 | if (atomic_inc_return(&file->sm_ref) > 1) | ||
| 299 | break; | ||
| 295 | set_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); | 300 | set_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); |
| 301 | } | ||
| 296 | 302 | ||
| 297 | if (!(file->flags & FTRACE_EVENT_FL_ENABLED)) { | 303 | if (!(file->flags & FTRACE_EVENT_FL_ENABLED)) { |
| 298 | 304 | ||
| @@ -623,6 +629,8 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
| 623 | if (file->flags & FTRACE_EVENT_FL_ENABLED) { | 629 | if (file->flags & FTRACE_EVENT_FL_ENABLED) { |
| 624 | if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED) | 630 | if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED) |
| 625 | buf = "0*\n"; | 631 | buf = "0*\n"; |
| 632 | else if (file->flags & FTRACE_EVENT_FL_SOFT_MODE) | ||
| 633 | buf = "1*\n"; | ||
| 626 | else | 634 | else |
| 627 | buf = "1\n"; | 635 | buf = "1\n"; |
| 628 | } else | 636 | } else |
| @@ -1521,6 +1529,24 @@ __register_event(struct ftrace_event_call *call, struct module *mod) | |||
| 1521 | return 0; | 1529 | return 0; |
| 1522 | } | 1530 | } |
| 1523 | 1531 | ||
| 1532 | static struct ftrace_event_file * | ||
| 1533 | trace_create_new_event(struct ftrace_event_call *call, | ||
| 1534 | struct trace_array *tr) | ||
| 1535 | { | ||
| 1536 | struct ftrace_event_file *file; | ||
| 1537 | |||
| 1538 | file = kmem_cache_alloc(file_cachep, GFP_TRACE); | ||
| 1539 | if (!file) | ||
| 1540 | return NULL; | ||
| 1541 | |||
| 1542 | file->event_call = call; | ||
| 1543 | file->tr = tr; | ||
| 1544 | atomic_set(&file->sm_ref, 0); | ||
| 1545 | list_add(&file->list, &tr->events); | ||
| 1546 | |||
| 1547 | return file; | ||
| 1548 | } | ||
| 1549 | |||
| 1524 | /* Add an event to a trace directory */ | 1550 | /* Add an event to a trace directory */ |
| 1525 | static int | 1551 | static int |
| 1526 | __trace_add_new_event(struct ftrace_event_call *call, | 1552 | __trace_add_new_event(struct ftrace_event_call *call, |
| @@ -1532,14 +1558,10 @@ __trace_add_new_event(struct ftrace_event_call *call, | |||
| 1532 | { | 1558 | { |
| 1533 | struct ftrace_event_file *file; | 1559 | struct ftrace_event_file *file; |
| 1534 | 1560 | ||
| 1535 | file = kmem_cache_alloc(file_cachep, GFP_TRACE); | 1561 | file = trace_create_new_event(call, tr); |
| 1536 | if (!file) | 1562 | if (!file) |
| 1537 | return -ENOMEM; | 1563 | return -ENOMEM; |
| 1538 | 1564 | ||
| 1539 | file->event_call = call; | ||
| 1540 | file->tr = tr; | ||
| 1541 | list_add(&file->list, &tr->events); | ||
| 1542 | |||
| 1543 | return event_create_dir(tr->event_dir, file, id, enable, filter, format); | 1565 | return event_create_dir(tr->event_dir, file, id, enable, filter, format); |
| 1544 | } | 1566 | } |
| 1545 | 1567 | ||
| @@ -1554,14 +1576,10 @@ __trace_early_add_new_event(struct ftrace_event_call *call, | |||
| 1554 | { | 1576 | { |
| 1555 | struct ftrace_event_file *file; | 1577 | struct ftrace_event_file *file; |
| 1556 | 1578 | ||
| 1557 | file = kmem_cache_alloc(file_cachep, GFP_TRACE); | 1579 | file = trace_create_new_event(call, tr); |
| 1558 | if (!file) | 1580 | if (!file) |
| 1559 | return -ENOMEM; | 1581 | return -ENOMEM; |
| 1560 | 1582 | ||
| 1561 | file->event_call = call; | ||
| 1562 | file->tr = tr; | ||
| 1563 | list_add(&file->list, &tr->events); | ||
| 1564 | |||
| 1565 | return 0; | 1583 | return 0; |
| 1566 | } | 1584 | } |
| 1567 | 1585 | ||
| @@ -2061,8 +2079,18 @@ event_enable_func(struct ftrace_hash *hash, | |||
| 2061 | if (ret < 0) | 2079 | if (ret < 0) |
| 2062 | goto out_put; | 2080 | goto out_put; |
| 2063 | ret = register_ftrace_function_probe(glob, ops, data); | 2081 | ret = register_ftrace_function_probe(glob, ops, data); |
| 2064 | if (!ret) | 2082 | /* |
| 2083 | * The above returns on success the # of functions enabled, | ||
| 2084 | * but if it didn't find any functions it returns zero. | ||
| 2085 | * Consider no functions a failure too. | ||
| 2086 | */ | ||
| 2087 | if (!ret) { | ||
| 2088 | ret = -ENOENT; | ||
| 2089 | goto out_disable; | ||
| 2090 | } else if (ret < 0) | ||
| 2065 | goto out_disable; | 2091 | goto out_disable; |
| 2092 | /* Just return zero, not the number of enabled functions */ | ||
| 2093 | ret = 0; | ||
| 2066 | out: | 2094 | out: |
| 2067 | mutex_unlock(&event_mutex); | 2095 | mutex_unlock(&event_mutex); |
| 2068 | return ret; | 2096 | return ret; |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1865d5f76538..636d45fe69b3 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | /** | 27 | /** |
| 28 | * Kprobe event core functions | 28 | * Kprobe event core functions |
| 29 | */ | 29 | */ |
| 30 | |||
| 31 | struct trace_probe { | 30 | struct trace_probe { |
| 32 | struct list_head list; | 31 | struct list_head list; |
| 33 | struct kretprobe rp; /* Use rp.kp for kprobe use */ | 32 | struct kretprobe rp; /* Use rp.kp for kprobe use */ |
| @@ -36,6 +35,7 @@ struct trace_probe { | |||
| 36 | const char *symbol; /* symbol name */ | 35 | const char *symbol; /* symbol name */ |
| 37 | struct ftrace_event_class class; | 36 | struct ftrace_event_class class; |
| 38 | struct ftrace_event_call call; | 37 | struct ftrace_event_call call; |
| 38 | struct ftrace_event_file **files; | ||
| 39 | ssize_t size; /* trace entry size */ | 39 | ssize_t size; /* trace entry size */ |
| 40 | unsigned int nr_args; | 40 | unsigned int nr_args; |
| 41 | struct probe_arg args[]; | 41 | struct probe_arg args[]; |
| @@ -46,7 +46,7 @@ struct trace_probe { | |||
| 46 | (sizeof(struct probe_arg) * (n))) | 46 | (sizeof(struct probe_arg) * (n))) |
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | static __kprobes int trace_probe_is_return(struct trace_probe *tp) | 49 | static __kprobes bool trace_probe_is_return(struct trace_probe *tp) |
| 50 | { | 50 | { |
| 51 | return tp->rp.handler != NULL; | 51 | return tp->rp.handler != NULL; |
| 52 | } | 52 | } |
| @@ -183,12 +183,57 @@ static struct trace_probe *find_trace_probe(const char *event, | |||
| 183 | return NULL; | 183 | return NULL; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | /* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ | 186 | static int trace_probe_nr_files(struct trace_probe *tp) |
| 187 | static int enable_trace_probe(struct trace_probe *tp, int flag) | 187 | { |
| 188 | struct ftrace_event_file **file = tp->files; | ||
| 189 | int ret = 0; | ||
| 190 | |||
| 191 | if (file) | ||
| 192 | while (*(file++)) | ||
| 193 | ret++; | ||
| 194 | |||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 198 | static DEFINE_MUTEX(probe_enable_lock); | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Enable trace_probe | ||
| 202 | * if the file is NULL, enable "perf" handler, or enable "trace" handler. | ||
| 203 | */ | ||
| 204 | static int | ||
| 205 | enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | ||
| 188 | { | 206 | { |
| 189 | int ret = 0; | 207 | int ret = 0; |
| 190 | 208 | ||
| 191 | tp->flags |= flag; | 209 | mutex_lock(&probe_enable_lock); |
| 210 | |||
| 211 | if (file) { | ||
| 212 | struct ftrace_event_file **new, **old = tp->files; | ||
| 213 | int n = trace_probe_nr_files(tp); | ||
| 214 | |||
| 215 | /* 1 is for new one and 1 is for stopper */ | ||
| 216 | new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *), | ||
| 217 | GFP_KERNEL); | ||
| 218 | if (!new) { | ||
| 219 | ret = -ENOMEM; | ||
| 220 | goto out_unlock; | ||
| 221 | } | ||
| 222 | memcpy(new, old, n * sizeof(struct ftrace_event_file *)); | ||
| 223 | new[n] = file; | ||
| 224 | /* The last one keeps a NULL */ | ||
| 225 | |||
| 226 | rcu_assign_pointer(tp->files, new); | ||
| 227 | tp->flags |= TP_FLAG_TRACE; | ||
| 228 | |||
| 229 | if (old) { | ||
| 230 | /* Make sure the probe is done with old files */ | ||
| 231 | synchronize_sched(); | ||
| 232 | kfree(old); | ||
| 233 | } | ||
| 234 | } else | ||
| 235 | tp->flags |= TP_FLAG_PROFILE; | ||
| 236 | |||
| 192 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && | 237 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && |
| 193 | !trace_probe_has_gone(tp)) { | 238 | !trace_probe_has_gone(tp)) { |
| 194 | if (trace_probe_is_return(tp)) | 239 | if (trace_probe_is_return(tp)) |
| @@ -197,19 +242,83 @@ static int enable_trace_probe(struct trace_probe *tp, int flag) | |||
| 197 | ret = enable_kprobe(&tp->rp.kp); | 242 | ret = enable_kprobe(&tp->rp.kp); |
| 198 | } | 243 | } |
| 199 | 244 | ||
| 245 | out_unlock: | ||
| 246 | mutex_unlock(&probe_enable_lock); | ||
| 247 | |||
| 200 | return ret; | 248 | return ret; |
| 201 | } | 249 | } |
| 202 | 250 | ||
| 203 | /* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ | 251 | static int |
| 204 | static void disable_trace_probe(struct trace_probe *tp, int flag) | 252 | trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) |
| 253 | { | ||
| 254 | int i; | ||
| 255 | |||
| 256 | if (tp->files) { | ||
| 257 | for (i = 0; tp->files[i]; i++) | ||
| 258 | if (tp->files[i] == file) | ||
| 259 | return i; | ||
| 260 | } | ||
| 261 | |||
| 262 | return -1; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* | ||
| 266 | * Disable trace_probe | ||
| 267 | * if the file is NULL, disable "perf" handler, or disable "trace" handler. | ||
| 268 | */ | ||
| 269 | static int | ||
| 270 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | ||
| 205 | { | 271 | { |
| 206 | tp->flags &= ~flag; | 272 | int ret = 0; |
| 273 | |||
| 274 | mutex_lock(&probe_enable_lock); | ||
| 275 | |||
| 276 | if (file) { | ||
| 277 | struct ftrace_event_file **new, **old = tp->files; | ||
| 278 | int n = trace_probe_nr_files(tp); | ||
| 279 | int i, j; | ||
| 280 | |||
| 281 | if (n == 0 || trace_probe_file_index(tp, file) < 0) { | ||
| 282 | ret = -EINVAL; | ||
| 283 | goto out_unlock; | ||
| 284 | } | ||
| 285 | |||
| 286 | if (n == 1) { /* Remove the last file */ | ||
| 287 | tp->flags &= ~TP_FLAG_TRACE; | ||
| 288 | new = NULL; | ||
| 289 | } else { | ||
| 290 | new = kzalloc(n * sizeof(struct ftrace_event_file *), | ||
| 291 | GFP_KERNEL); | ||
| 292 | if (!new) { | ||
| 293 | ret = -ENOMEM; | ||
| 294 | goto out_unlock; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* This copy & check loop copies the NULL stopper too */ | ||
| 298 | for (i = 0, j = 0; j < n && i < n + 1; i++) | ||
| 299 | if (old[i] != file) | ||
| 300 | new[j++] = old[i]; | ||
| 301 | } | ||
| 302 | |||
| 303 | rcu_assign_pointer(tp->files, new); | ||
| 304 | |||
| 305 | /* Make sure the probe is done with old files */ | ||
| 306 | synchronize_sched(); | ||
| 307 | kfree(old); | ||
| 308 | } else | ||
| 309 | tp->flags &= ~TP_FLAG_PROFILE; | ||
| 310 | |||
| 207 | if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { | 311 | if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { |
| 208 | if (trace_probe_is_return(tp)) | 312 | if (trace_probe_is_return(tp)) |
| 209 | disable_kretprobe(&tp->rp); | 313 | disable_kretprobe(&tp->rp); |
| 210 | else | 314 | else |
| 211 | disable_kprobe(&tp->rp.kp); | 315 | disable_kprobe(&tp->rp.kp); |
| 212 | } | 316 | } |
| 317 | |||
| 318 | out_unlock: | ||
| 319 | mutex_unlock(&probe_enable_lock); | ||
| 320 | |||
| 321 | return ret; | ||
| 213 | } | 322 | } |
| 214 | 323 | ||
| 215 | /* Internal register function - just handle k*probes and flags */ | 324 | /* Internal register function - just handle k*probes and flags */ |
| @@ -723,9 +832,10 @@ static __kprobes void store_trace_args(int ent_size, struct trace_probe *tp, | |||
| 723 | } | 832 | } |
| 724 | 833 | ||
| 725 | /* Kprobe handler */ | 834 | /* Kprobe handler */ |
| 726 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 835 | static __kprobes void |
| 836 | __kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs, | ||
| 837 | struct ftrace_event_file *ftrace_file) | ||
| 727 | { | 838 | { |
| 728 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | ||
| 729 | struct kprobe_trace_entry_head *entry; | 839 | struct kprobe_trace_entry_head *entry; |
| 730 | struct ring_buffer_event *event; | 840 | struct ring_buffer_event *event; |
| 731 | struct ring_buffer *buffer; | 841 | struct ring_buffer *buffer; |
| @@ -733,7 +843,10 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 733 | unsigned long irq_flags; | 843 | unsigned long irq_flags; |
| 734 | struct ftrace_event_call *call = &tp->call; | 844 | struct ftrace_event_call *call = &tp->call; |
| 735 | 845 | ||
| 736 | tp->nhit++; | 846 | WARN_ON(call != ftrace_file->event_call); |
| 847 | |||
| 848 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | ||
| 849 | return; | ||
| 737 | 850 | ||
| 738 | local_save_flags(irq_flags); | 851 | local_save_flags(irq_flags); |
| 739 | pc = preempt_count(); | 852 | pc = preempt_count(); |
| @@ -741,13 +854,14 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 741 | dsize = __get_data_size(tp, regs); | 854 | dsize = __get_data_size(tp, regs); |
| 742 | size = sizeof(*entry) + tp->size + dsize; | 855 | size = sizeof(*entry) + tp->size + dsize; |
| 743 | 856 | ||
| 744 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 857 | event = trace_event_buffer_lock_reserve(&buffer, ftrace_file, |
| 745 | size, irq_flags, pc); | 858 | call->event.type, |
| 859 | size, irq_flags, pc); | ||
| 746 | if (!event) | 860 | if (!event) |
| 747 | return; | 861 | return; |
| 748 | 862 | ||
| 749 | entry = ring_buffer_event_data(event); | 863 | entry = ring_buffer_event_data(event); |
| 750 | entry->ip = (unsigned long)kp->addr; | 864 | entry->ip = (unsigned long)tp->rp.kp.addr; |
| 751 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 865 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
| 752 | 866 | ||
| 753 | if (!filter_current_check_discard(buffer, call, entry, event)) | 867 | if (!filter_current_check_discard(buffer, call, entry, event)) |
| @@ -755,11 +869,24 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 755 | irq_flags, pc, regs); | 869 | irq_flags, pc, regs); |
| 756 | } | 870 | } |
| 757 | 871 | ||
| 872 | static __kprobes void | ||
| 873 | kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) | ||
| 874 | { | ||
| 875 | struct ftrace_event_file **file = tp->files; | ||
| 876 | |||
| 877 | /* Note: preempt is already disabled around the kprobe handler */ | ||
| 878 | while (*file) { | ||
| 879 | __kprobe_trace_func(tp, regs, *file); | ||
| 880 | file++; | ||
| 881 | } | ||
| 882 | } | ||
| 883 | |||
| 758 | /* Kretprobe handler */ | 884 | /* Kretprobe handler */ |
| 759 | static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | 885 | static __kprobes void |
| 760 | struct pt_regs *regs) | 886 | __kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
| 887 | struct pt_regs *regs, | ||
| 888 | struct ftrace_event_file *ftrace_file) | ||
| 761 | { | 889 | { |
| 762 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | ||
| 763 | struct kretprobe_trace_entry_head *entry; | 890 | struct kretprobe_trace_entry_head *entry; |
| 764 | struct ring_buffer_event *event; | 891 | struct ring_buffer_event *event; |
| 765 | struct ring_buffer *buffer; | 892 | struct ring_buffer *buffer; |
| @@ -767,14 +894,20 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 767 | unsigned long irq_flags; | 894 | unsigned long irq_flags; |
| 768 | struct ftrace_event_call *call = &tp->call; | 895 | struct ftrace_event_call *call = &tp->call; |
| 769 | 896 | ||
| 897 | WARN_ON(call != ftrace_file->event_call); | ||
| 898 | |||
| 899 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | ||
| 900 | return; | ||
| 901 | |||
| 770 | local_save_flags(irq_flags); | 902 | local_save_flags(irq_flags); |
| 771 | pc = preempt_count(); | 903 | pc = preempt_count(); |
| 772 | 904 | ||
| 773 | dsize = __get_data_size(tp, regs); | 905 | dsize = __get_data_size(tp, regs); |
| 774 | size = sizeof(*entry) + tp->size + dsize; | 906 | size = sizeof(*entry) + tp->size + dsize; |
| 775 | 907 | ||
| 776 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 908 | event = trace_event_buffer_lock_reserve(&buffer, ftrace_file, |
| 777 | size, irq_flags, pc); | 909 | call->event.type, |
| 910 | size, irq_flags, pc); | ||
| 778 | if (!event) | 911 | if (!event) |
| 779 | return; | 912 | return; |
| 780 | 913 | ||
| @@ -788,6 +921,19 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 788 | irq_flags, pc, regs); | 921 | irq_flags, pc, regs); |
| 789 | } | 922 | } |
| 790 | 923 | ||
| 924 | static __kprobes void | ||
| 925 | kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, | ||
| 926 | struct pt_regs *regs) | ||
| 927 | { | ||
| 928 | struct ftrace_event_file **file = tp->files; | ||
| 929 | |||
| 930 | /* Note: preempt is already disabled around the kprobe handler */ | ||
| 931 | while (*file) { | ||
| 932 | __kretprobe_trace_func(tp, ri, regs, *file); | ||
| 933 | file++; | ||
| 934 | } | ||
| 935 | } | ||
| 936 | |||
| 791 | /* Event entry printers */ | 937 | /* Event entry printers */ |
| 792 | enum print_line_t | 938 | enum print_line_t |
| 793 | print_kprobe_event(struct trace_iterator *iter, int flags, | 939 | print_kprobe_event(struct trace_iterator *iter, int flags, |
| @@ -975,10 +1121,9 @@ static int set_print_fmt(struct trace_probe *tp) | |||
| 975 | #ifdef CONFIG_PERF_EVENTS | 1121 | #ifdef CONFIG_PERF_EVENTS |
| 976 | 1122 | ||
| 977 | /* Kprobe profile handler */ | 1123 | /* Kprobe profile handler */ |
| 978 | static __kprobes void kprobe_perf_func(struct kprobe *kp, | 1124 | static __kprobes void |
| 979 | struct pt_regs *regs) | 1125 | kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) |
| 980 | { | 1126 | { |
| 981 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | ||
| 982 | struct ftrace_event_call *call = &tp->call; | 1127 | struct ftrace_event_call *call = &tp->call; |
| 983 | struct kprobe_trace_entry_head *entry; | 1128 | struct kprobe_trace_entry_head *entry; |
| 984 | struct hlist_head *head; | 1129 | struct hlist_head *head; |
| @@ -997,7 +1142,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
| 997 | if (!entry) | 1142 | if (!entry) |
| 998 | return; | 1143 | return; |
| 999 | 1144 | ||
| 1000 | entry->ip = (unsigned long)kp->addr; | 1145 | entry->ip = (unsigned long)tp->rp.kp.addr; |
| 1001 | memset(&entry[1], 0, dsize); | 1146 | memset(&entry[1], 0, dsize); |
| 1002 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 1147 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
| 1003 | 1148 | ||
| @@ -1007,10 +1152,10 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
| 1007 | } | 1152 | } |
| 1008 | 1153 | ||
| 1009 | /* Kretprobe profile handler */ | 1154 | /* Kretprobe profile handler */ |
| 1010 | static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | 1155 | static __kprobes void |
| 1011 | struct pt_regs *regs) | 1156 | kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
| 1157 | struct pt_regs *regs) | ||
| 1012 | { | 1158 | { |
| 1013 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | ||
| 1014 | struct ftrace_event_call *call = &tp->call; | 1159 | struct ftrace_event_call *call = &tp->call; |
| 1015 | struct kretprobe_trace_entry_head *entry; | 1160 | struct kretprobe_trace_entry_head *entry; |
| 1016 | struct hlist_head *head; | 1161 | struct hlist_head *head; |
| @@ -1044,20 +1189,19 @@ int kprobe_register(struct ftrace_event_call *event, | |||
| 1044 | enum trace_reg type, void *data) | 1189 | enum trace_reg type, void *data) |
| 1045 | { | 1190 | { |
| 1046 | struct trace_probe *tp = (struct trace_probe *)event->data; | 1191 | struct trace_probe *tp = (struct trace_probe *)event->data; |
| 1192 | struct ftrace_event_file *file = data; | ||
| 1047 | 1193 | ||
| 1048 | switch (type) { | 1194 | switch (type) { |
| 1049 | case TRACE_REG_REGISTER: | 1195 | case TRACE_REG_REGISTER: |
| 1050 | return enable_trace_probe(tp, TP_FLAG_TRACE); | 1196 | return enable_trace_probe(tp, file); |
| 1051 | case TRACE_REG_UNREGISTER: | 1197 | case TRACE_REG_UNREGISTER: |
| 1052 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1198 | return disable_trace_probe(tp, file); |
| 1053 | return 0; | ||
| 1054 | 1199 | ||
| 1055 | #ifdef CONFIG_PERF_EVENTS | 1200 | #ifdef CONFIG_PERF_EVENTS |
| 1056 | case TRACE_REG_PERF_REGISTER: | 1201 | case TRACE_REG_PERF_REGISTER: |
| 1057 | return enable_trace_probe(tp, TP_FLAG_PROFILE); | 1202 | return enable_trace_probe(tp, NULL); |
| 1058 | case TRACE_REG_PERF_UNREGISTER: | 1203 | case TRACE_REG_PERF_UNREGISTER: |
| 1059 | disable_trace_probe(tp, TP_FLAG_PROFILE); | 1204 | return disable_trace_probe(tp, NULL); |
| 1060 | return 0; | ||
| 1061 | case TRACE_REG_PERF_OPEN: | 1205 | case TRACE_REG_PERF_OPEN: |
| 1062 | case TRACE_REG_PERF_CLOSE: | 1206 | case TRACE_REG_PERF_CLOSE: |
| 1063 | case TRACE_REG_PERF_ADD: | 1207 | case TRACE_REG_PERF_ADD: |
| @@ -1073,11 +1217,13 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) | |||
| 1073 | { | 1217 | { |
| 1074 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1218 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
| 1075 | 1219 | ||
| 1220 | tp->nhit++; | ||
| 1221 | |||
| 1076 | if (tp->flags & TP_FLAG_TRACE) | 1222 | if (tp->flags & TP_FLAG_TRACE) |
| 1077 | kprobe_trace_func(kp, regs); | 1223 | kprobe_trace_func(tp, regs); |
| 1078 | #ifdef CONFIG_PERF_EVENTS | 1224 | #ifdef CONFIG_PERF_EVENTS |
| 1079 | if (tp->flags & TP_FLAG_PROFILE) | 1225 | if (tp->flags & TP_FLAG_PROFILE) |
| 1080 | kprobe_perf_func(kp, regs); | 1226 | kprobe_perf_func(tp, regs); |
| 1081 | #endif | 1227 | #endif |
| 1082 | return 0; /* We don't tweek kernel, so just return 0 */ | 1228 | return 0; /* We don't tweek kernel, so just return 0 */ |
| 1083 | } | 1229 | } |
| @@ -1087,11 +1233,13 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 1087 | { | 1233 | { |
| 1088 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1234 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
| 1089 | 1235 | ||
| 1236 | tp->nhit++; | ||
| 1237 | |||
| 1090 | if (tp->flags & TP_FLAG_TRACE) | 1238 | if (tp->flags & TP_FLAG_TRACE) |
| 1091 | kretprobe_trace_func(ri, regs); | 1239 | kretprobe_trace_func(tp, ri, regs); |
| 1092 | #ifdef CONFIG_PERF_EVENTS | 1240 | #ifdef CONFIG_PERF_EVENTS |
| 1093 | if (tp->flags & TP_FLAG_PROFILE) | 1241 | if (tp->flags & TP_FLAG_PROFILE) |
| 1094 | kretprobe_perf_func(ri, regs); | 1242 | kretprobe_perf_func(tp, ri, regs); |
| 1095 | #endif | 1243 | #endif |
| 1096 | return 0; /* We don't tweek kernel, so just return 0 */ | 1244 | return 0; /* We don't tweek kernel, so just return 0 */ |
| 1097 | } | 1245 | } |
| @@ -1189,11 +1337,24 @@ static __used int kprobe_trace_selftest_target(int a1, int a2, int a3, | |||
| 1189 | return a1 + a2 + a3 + a4 + a5 + a6; | 1337 | return a1 + a2 + a3 + a4 + a5 + a6; |
| 1190 | } | 1338 | } |
| 1191 | 1339 | ||
| 1340 | static struct ftrace_event_file * | ||
| 1341 | find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr) | ||
| 1342 | { | ||
| 1343 | struct ftrace_event_file *file; | ||
| 1344 | |||
| 1345 | list_for_each_entry(file, &tr->events, list) | ||
| 1346 | if (file->event_call == &tp->call) | ||
| 1347 | return file; | ||
| 1348 | |||
| 1349 | return NULL; | ||
| 1350 | } | ||
| 1351 | |||
| 1192 | static __init int kprobe_trace_self_tests_init(void) | 1352 | static __init int kprobe_trace_self_tests_init(void) |
| 1193 | { | 1353 | { |
| 1194 | int ret, warn = 0; | 1354 | int ret, warn = 0; |
| 1195 | int (*target)(int, int, int, int, int, int); | 1355 | int (*target)(int, int, int, int, int, int); |
| 1196 | struct trace_probe *tp; | 1356 | struct trace_probe *tp; |
| 1357 | struct ftrace_event_file *file; | ||
| 1197 | 1358 | ||
| 1198 | target = kprobe_trace_selftest_target; | 1359 | target = kprobe_trace_selftest_target; |
| 1199 | 1360 | ||
| @@ -1203,31 +1364,43 @@ static __init int kprobe_trace_self_tests_init(void) | |||
| 1203 | "$stack $stack0 +0($stack)", | 1364 | "$stack $stack0 +0($stack)", |
| 1204 | create_trace_probe); | 1365 | create_trace_probe); |
| 1205 | if (WARN_ON_ONCE(ret)) { | 1366 | if (WARN_ON_ONCE(ret)) { |
| 1206 | pr_warning("error on probing function entry.\n"); | 1367 | pr_warn("error on probing function entry.\n"); |
| 1207 | warn++; | 1368 | warn++; |
| 1208 | } else { | 1369 | } else { |
| 1209 | /* Enable trace point */ | 1370 | /* Enable trace point */ |
| 1210 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); | 1371 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); |
| 1211 | if (WARN_ON_ONCE(tp == NULL)) { | 1372 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1212 | pr_warning("error on getting new probe.\n"); | 1373 | pr_warn("error on getting new probe.\n"); |
| 1213 | warn++; | 1374 | warn++; |
| 1214 | } else | 1375 | } else { |
| 1215 | enable_trace_probe(tp, TP_FLAG_TRACE); | 1376 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1377 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1378 | pr_warn("error on getting probe file.\n"); | ||
| 1379 | warn++; | ||
| 1380 | } else | ||
| 1381 | enable_trace_probe(tp, file); | ||
| 1382 | } | ||
| 1216 | } | 1383 | } |
| 1217 | 1384 | ||
| 1218 | ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " | 1385 | ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " |
| 1219 | "$retval", create_trace_probe); | 1386 | "$retval", create_trace_probe); |
| 1220 | if (WARN_ON_ONCE(ret)) { | 1387 | if (WARN_ON_ONCE(ret)) { |
| 1221 | pr_warning("error on probing function return.\n"); | 1388 | pr_warn("error on probing function return.\n"); |
| 1222 | warn++; | 1389 | warn++; |
| 1223 | } else { | 1390 | } else { |
| 1224 | /* Enable trace point */ | 1391 | /* Enable trace point */ |
| 1225 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); | 1392 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); |
| 1226 | if (WARN_ON_ONCE(tp == NULL)) { | 1393 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1227 | pr_warning("error on getting new probe.\n"); | 1394 | pr_warn("error on getting 2nd new probe.\n"); |
| 1228 | warn++; | 1395 | warn++; |
| 1229 | } else | 1396 | } else { |
| 1230 | enable_trace_probe(tp, TP_FLAG_TRACE); | 1397 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1398 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1399 | pr_warn("error on getting probe file.\n"); | ||
| 1400 | warn++; | ||
| 1401 | } else | ||
| 1402 | enable_trace_probe(tp, file); | ||
| 1403 | } | ||
| 1231 | } | 1404 | } |
| 1232 | 1405 | ||
| 1233 | if (warn) | 1406 | if (warn) |
| @@ -1238,27 +1411,39 @@ static __init int kprobe_trace_self_tests_init(void) | |||
| 1238 | /* Disable trace points before removing it */ | 1411 | /* Disable trace points before removing it */ |
| 1239 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); | 1412 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); |
| 1240 | if (WARN_ON_ONCE(tp == NULL)) { | 1413 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1241 | pr_warning("error on getting test probe.\n"); | 1414 | pr_warn("error on getting test probe.\n"); |
| 1242 | warn++; | 1415 | warn++; |
| 1243 | } else | 1416 | } else { |
| 1244 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1417 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1418 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1419 | pr_warn("error on getting probe file.\n"); | ||
| 1420 | warn++; | ||
| 1421 | } else | ||
| 1422 | disable_trace_probe(tp, file); | ||
| 1423 | } | ||
| 1245 | 1424 | ||
| 1246 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); | 1425 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); |
| 1247 | if (WARN_ON_ONCE(tp == NULL)) { | 1426 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1248 | pr_warning("error on getting 2nd test probe.\n"); | 1427 | pr_warn("error on getting 2nd test probe.\n"); |
| 1249 | warn++; | 1428 | warn++; |
| 1250 | } else | 1429 | } else { |
| 1251 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1430 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1431 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1432 | pr_warn("error on getting probe file.\n"); | ||
| 1433 | warn++; | ||
| 1434 | } else | ||
| 1435 | disable_trace_probe(tp, file); | ||
| 1436 | } | ||
| 1252 | 1437 | ||
| 1253 | ret = traceprobe_command("-:testprobe", create_trace_probe); | 1438 | ret = traceprobe_command("-:testprobe", create_trace_probe); |
| 1254 | if (WARN_ON_ONCE(ret)) { | 1439 | if (WARN_ON_ONCE(ret)) { |
| 1255 | pr_warning("error on deleting a probe.\n"); | 1440 | pr_warn("error on deleting a probe.\n"); |
| 1256 | warn++; | 1441 | warn++; |
| 1257 | } | 1442 | } |
| 1258 | 1443 | ||
| 1259 | ret = traceprobe_command("-:testprobe2", create_trace_probe); | 1444 | ret = traceprobe_command("-:testprobe2", create_trace_probe); |
| 1260 | if (WARN_ON_ONCE(ret)) { | 1445 | if (WARN_ON_ONCE(ret)) { |
| 1261 | pr_warning("error on deleting a probe.\n"); | 1446 | pr_warn("error on deleting a probe.\n"); |
| 1262 | warn++; | 1447 | warn++; |
| 1263 | } | 1448 | } |
| 1264 | 1449 | ||
