summaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ftrace.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index b9691ee8f6c1..27bb2e61276e 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3755,23 +3755,24 @@ static void __enable_ftrace_function_probe(struct ftrace_ops_hash *old_hash)
3755 ftrace_probe_registered = 1; 3755 ftrace_probe_registered = 1;
3756} 3756}
3757 3757
3758static void __disable_ftrace_function_probe(void) 3758static bool __disable_ftrace_function_probe(void)
3759{ 3759{
3760 int i; 3760 int i;
3761 3761
3762 if (!ftrace_probe_registered) 3762 if (!ftrace_probe_registered)
3763 return; 3763 return false;
3764 3764
3765 for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 3765 for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
3766 struct hlist_head *hhd = &ftrace_func_hash[i]; 3766 struct hlist_head *hhd = &ftrace_func_hash[i];
3767 if (hhd->first) 3767 if (hhd->first)
3768 return; 3768 return false;
3769 } 3769 }
3770 3770
3771 /* no more funcs left */ 3771 /* no more funcs left */
3772 ftrace_shutdown(&trace_probe_ops, 0); 3772 ftrace_shutdown(&trace_probe_ops, 0);
3773 3773
3774 ftrace_probe_registered = 0; 3774 ftrace_probe_registered = 0;
3775 return true;
3775} 3776}
3776 3777
3777 3778
@@ -3901,6 +3902,7 @@ static void
3901__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 3902__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3902 void *data, int flags) 3903 void *data, int flags)
3903{ 3904{
3905 struct ftrace_ops_hash old_hash_ops;
3904 struct ftrace_func_entry *rec_entry; 3906 struct ftrace_func_entry *rec_entry;
3905 struct ftrace_func_probe *entry; 3907 struct ftrace_func_probe *entry;
3906 struct ftrace_func_probe *p; 3908 struct ftrace_func_probe *p;
@@ -3912,6 +3914,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3912 struct hlist_node *tmp; 3914 struct hlist_node *tmp;
3913 char str[KSYM_SYMBOL_LEN]; 3915 char str[KSYM_SYMBOL_LEN];
3914 int i, ret; 3916 int i, ret;
3917 bool disabled;
3915 3918
3916 if (glob && (strcmp(glob, "*") == 0 || !strlen(glob))) 3919 if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
3917 func_g.search = NULL; 3920 func_g.search = NULL;
@@ -3930,6 +3933,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3930 3933
3931 mutex_lock(&trace_probe_ops.func_hash->regex_lock); 3934 mutex_lock(&trace_probe_ops.func_hash->regex_lock);
3932 3935
3936 old_hash_ops.filter_hash = old_hash;
3937 /* Probes only have filters */
3938 old_hash_ops.notrace_hash = NULL;
3939
3933 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 3940 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3934 if (!hash) 3941 if (!hash)
3935 /* Hmm, should report this somehow */ 3942 /* Hmm, should report this somehow */
@@ -3967,12 +3974,17 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3967 } 3974 }
3968 } 3975 }
3969 mutex_lock(&ftrace_lock); 3976 mutex_lock(&ftrace_lock);
3970 __disable_ftrace_function_probe(); 3977 disabled = __disable_ftrace_function_probe();
3971 /* 3978 /*
3972 * Remove after the disable is called. Otherwise, if the last 3979 * Remove after the disable is called. Otherwise, if the last
3973 * probe is removed, a null hash means *all enabled*. 3980 * probe is removed, a null hash means *all enabled*.
3974 */ 3981 */
3975 ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash); 3982 ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3983
3984 /* still need to update the function call sites */
3985 if (ftrace_enabled && !disabled)
3986 ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS,
3987 &old_hash_ops);
3976 synchronize_sched(); 3988 synchronize_sched();
3977 if (!ret) 3989 if (!ret)
3978 free_ftrace_hash_rcu(old_hash); 3990 free_ftrace_hash_rcu(old_hash);