aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c98
1 files changed, 69 insertions, 29 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index b3fde6d7b7fc..8a5c017bb50c 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -486,7 +486,6 @@ struct ftrace_profile_stat {
486#define PROFILES_PER_PAGE \ 486#define PROFILES_PER_PAGE \
487 (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile)) 487 (PROFILE_RECORDS_SIZE / sizeof(struct ftrace_profile))
488 488
489static int ftrace_profile_bits __read_mostly;
490static int ftrace_profile_enabled __read_mostly; 489static int ftrace_profile_enabled __read_mostly;
491 490
492/* ftrace_profile_lock - synchronize the enable and disable of the profiler */ 491/* ftrace_profile_lock - synchronize the enable and disable of the profiler */
@@ -494,7 +493,8 @@ static DEFINE_MUTEX(ftrace_profile_lock);
494 493
495static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats); 494static DEFINE_PER_CPU(struct ftrace_profile_stat, ftrace_profile_stats);
496 495
497#define FTRACE_PROFILE_HASH_SIZE 1024 /* must be power of 2 */ 496#define FTRACE_PROFILE_HASH_BITS 10
497#define FTRACE_PROFILE_HASH_SIZE (1 << FTRACE_PROFILE_HASH_BITS)
498 498
499static void * 499static void *
500function_stat_next(void *v, int idx) 500function_stat_next(void *v, int idx)
@@ -676,7 +676,7 @@ int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)
676 676
677 pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE); 677 pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE);
678 678
679 for (i = 0; i < pages; i++) { 679 for (i = 1; i < pages; i++) {
680 pg->next = (void *)get_zeroed_page(GFP_KERNEL); 680 pg->next = (void *)get_zeroed_page(GFP_KERNEL);
681 if (!pg->next) 681 if (!pg->next)
682 goto out_free; 682 goto out_free;
@@ -724,13 +724,6 @@ static int ftrace_profile_init_cpu(int cpu)
724 if (!stat->hash) 724 if (!stat->hash)
725 return -ENOMEM; 725 return -ENOMEM;
726 726
727 if (!ftrace_profile_bits) {
728 size--;
729
730 for (; size; size >>= 1)
731 ftrace_profile_bits++;
732 }
733
734 /* Preallocate the function profiling pages */ 727 /* Preallocate the function profiling pages */
735 if (ftrace_profile_pages_init(stat) < 0) { 728 if (ftrace_profile_pages_init(stat) < 0) {
736 kfree(stat->hash); 729 kfree(stat->hash);
@@ -763,7 +756,7 @@ ftrace_find_profiled_func(struct ftrace_profile_stat *stat, unsigned long ip)
763 struct hlist_head *hhd; 756 struct hlist_head *hhd;
764 unsigned long key; 757 unsigned long key;
765 758
766 key = hash_long(ip, ftrace_profile_bits); 759 key = hash_long(ip, FTRACE_PROFILE_HASH_BITS);
767 hhd = &stat->hash[key]; 760 hhd = &stat->hash[key];
768 761
769 if (hlist_empty(hhd)) 762 if (hlist_empty(hhd))
@@ -782,7 +775,7 @@ static void ftrace_add_profile(struct ftrace_profile_stat *stat,
782{ 775{
783 unsigned long key; 776 unsigned long key;
784 777
785 key = hash_long(rec->ip, ftrace_profile_bits); 778 key = hash_long(rec->ip, FTRACE_PROFILE_HASH_BITS);
786 hlist_add_head_rcu(&rec->node, &stat->hash[key]); 779 hlist_add_head_rcu(&rec->node, &stat->hash[key]);
787} 780}
788 781
@@ -1079,7 +1072,7 @@ struct ftrace_func_probe {
1079 unsigned long flags; 1072 unsigned long flags;
1080 unsigned long ip; 1073 unsigned long ip;
1081 void *data; 1074 void *data;
1082 struct rcu_head rcu; 1075 struct list_head free_list;
1083}; 1076};
1084 1077
1085struct ftrace_func_entry { 1078struct ftrace_func_entry {
@@ -1329,7 +1322,6 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
1329 struct hlist_head *hhd; 1322 struct hlist_head *hhd;
1330 struct ftrace_hash *old_hash; 1323 struct ftrace_hash *old_hash;
1331 struct ftrace_hash *new_hash; 1324 struct ftrace_hash *new_hash;
1332 unsigned long key;
1333 int size = src->count; 1325 int size = src->count;
1334 int bits = 0; 1326 int bits = 0;
1335 int ret; 1327 int ret;
@@ -1372,10 +1364,6 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
1372 for (i = 0; i < size; i++) { 1364 for (i = 0; i < size; i++) {
1373 hhd = &src->buckets[i]; 1365 hhd = &src->buckets[i];
1374 hlist_for_each_entry_safe(entry, tn, hhd, hlist) { 1366 hlist_for_each_entry_safe(entry, tn, hhd, hlist) {
1375 if (bits > 0)
1376 key = hash_long(entry->ip, bits);
1377 else
1378 key = 0;
1379 remove_hash_entry(src, entry); 1367 remove_hash_entry(src, entry);
1380 __add_hash_entry(new_hash, entry); 1368 __add_hash_entry(new_hash, entry);
1381 } 1369 }
@@ -2973,28 +2961,27 @@ static void __disable_ftrace_function_probe(void)
2973} 2961}
2974 2962
2975 2963
2976static void ftrace_free_entry_rcu(struct rcu_head *rhp) 2964static void ftrace_free_entry(struct ftrace_func_probe *entry)
2977{ 2965{
2978 struct ftrace_func_probe *entry =
2979 container_of(rhp, struct ftrace_func_probe, rcu);
2980
2981 if (entry->ops->free) 2966 if (entry->ops->free)
2982 entry->ops->free(&entry->data); 2967 entry->ops->free(entry->ops, entry->ip, &entry->data);
2983 kfree(entry); 2968 kfree(entry);
2984} 2969}
2985 2970
2986
2987int 2971int
2988register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 2972register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
2989 void *data) 2973 void *data)
2990{ 2974{
2991 struct ftrace_func_probe *entry; 2975 struct ftrace_func_probe *entry;
2976 struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
2977 struct ftrace_hash *hash;
2992 struct ftrace_page *pg; 2978 struct ftrace_page *pg;
2993 struct dyn_ftrace *rec; 2979 struct dyn_ftrace *rec;
2994 int type, len, not; 2980 int type, len, not;
2995 unsigned long key; 2981 unsigned long key;
2996 int count = 0; 2982 int count = 0;
2997 char *search; 2983 char *search;
2984 int ret;
2998 2985
2999 type = filter_parse_regex(glob, strlen(glob), &search, &not); 2986 type = filter_parse_regex(glob, strlen(glob), &search, &not);
3000 len = strlen(search); 2987 len = strlen(search);
@@ -3005,8 +2992,16 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3005 2992
3006 mutex_lock(&ftrace_lock); 2993 mutex_lock(&ftrace_lock);
3007 2994
3008 if (unlikely(ftrace_disabled)) 2995 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
2996 if (!hash) {
2997 count = -ENOMEM;
3009 goto out_unlock; 2998 goto out_unlock;
2999 }
3000
3001 if (unlikely(ftrace_disabled)) {
3002 count = -ENODEV;
3003 goto out_unlock;
3004 }
3010 3005
3011 do_for_each_ftrace_rec(pg, rec) { 3006 do_for_each_ftrace_rec(pg, rec) {
3012 3007
@@ -3030,14 +3025,21 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3030 * for each function we find. We call the callback 3025 * for each function we find. We call the callback
3031 * to give the caller an opportunity to do so. 3026 * to give the caller an opportunity to do so.
3032 */ 3027 */
3033 if (ops->callback) { 3028 if (ops->init) {
3034 if (ops->callback(rec->ip, &entry->data) < 0) { 3029 if (ops->init(ops, rec->ip, &entry->data) < 0) {
3035 /* caller does not like this func */ 3030 /* caller does not like this func */
3036 kfree(entry); 3031 kfree(entry);
3037 continue; 3032 continue;
3038 } 3033 }
3039 } 3034 }
3040 3035
3036 ret = enter_record(hash, rec, 0);
3037 if (ret < 0) {
3038 kfree(entry);
3039 count = ret;
3040 goto out_unlock;
3041 }
3042
3041 entry->ops = ops; 3043 entry->ops = ops;
3042 entry->ip = rec->ip; 3044 entry->ip = rec->ip;
3043 3045
@@ -3045,10 +3047,16 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3045 hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]); 3047 hlist_add_head_rcu(&entry->node, &ftrace_func_hash[key]);
3046 3048
3047 } while_for_each_ftrace_rec(); 3049 } while_for_each_ftrace_rec();
3050
3051 ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3052 if (ret < 0)
3053 count = ret;
3054
3048 __enable_ftrace_function_probe(); 3055 __enable_ftrace_function_probe();
3049 3056
3050 out_unlock: 3057 out_unlock:
3051 mutex_unlock(&ftrace_lock); 3058 mutex_unlock(&ftrace_lock);
3059 free_ftrace_hash(hash);
3052 3060
3053 return count; 3061 return count;
3054} 3062}
@@ -3062,7 +3070,12 @@ static void
3062__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 3070__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3063 void *data, int flags) 3071 void *data, int flags)
3064{ 3072{
3073 struct ftrace_func_entry *rec_entry;
3065 struct ftrace_func_probe *entry; 3074 struct ftrace_func_probe *entry;
3075 struct ftrace_func_probe *p;
3076 struct ftrace_hash **orig_hash = &trace_probe_ops.filter_hash;
3077 struct list_head free_list;
3078 struct ftrace_hash *hash;
3066 struct hlist_node *tmp; 3079 struct hlist_node *tmp;
3067 char str[KSYM_SYMBOL_LEN]; 3080 char str[KSYM_SYMBOL_LEN];
3068 int type = MATCH_FULL; 3081 int type = MATCH_FULL;
@@ -3083,6 +3096,14 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3083 } 3096 }
3084 3097
3085 mutex_lock(&ftrace_lock); 3098 mutex_lock(&ftrace_lock);
3099
3100 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3101 if (!hash)
3102 /* Hmm, should report this somehow */
3103 goto out_unlock;
3104
3105 INIT_LIST_HEAD(&free_list);
3106
3086 for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 3107 for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
3087 struct hlist_head *hhd = &ftrace_func_hash[i]; 3108 struct hlist_head *hhd = &ftrace_func_hash[i];
3088 3109
@@ -3103,12 +3124,30 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3103 continue; 3124 continue;
3104 } 3125 }
3105 3126
3127 rec_entry = ftrace_lookup_ip(hash, entry->ip);
3128 /* It is possible more than one entry had this ip */
3129 if (rec_entry)
3130 free_hash_entry(hash, rec_entry);
3131
3106 hlist_del_rcu(&entry->node); 3132 hlist_del_rcu(&entry->node);
3107 call_rcu_sched(&entry->rcu, ftrace_free_entry_rcu); 3133 list_add(&entry->free_list, &free_list);
3108 } 3134 }
3109 } 3135 }
3110 __disable_ftrace_function_probe(); 3136 __disable_ftrace_function_probe();
3137 /*
3138 * Remove after the disable is called. Otherwise, if the last
3139 * probe is removed, a null hash means *all enabled*.
3140 */
3141 ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3142 synchronize_sched();
3143 list_for_each_entry_safe(entry, p, &free_list, free_list) {
3144 list_del(&entry->free_list);
3145 ftrace_free_entry(entry);
3146 }
3147
3148 out_unlock:
3111 mutex_unlock(&ftrace_lock); 3149 mutex_unlock(&ftrace_lock);
3150 free_ftrace_hash(hash);
3112} 3151}
3113 3152
3114void 3153void
@@ -3736,7 +3775,8 @@ out:
3736 if (fail) 3775 if (fail)
3737 return -EINVAL; 3776 return -EINVAL;
3738 3777
3739 ftrace_graph_filter_enabled = 1; 3778 ftrace_graph_filter_enabled = !!(*idx);
3779
3740 return 0; 3780 return 0;
3741} 3781}
3742 3782