aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-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 da87b3cba5b3..3bd975c8d9c9 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3736,23 +3736,24 @@ static void __enable_ftrace_function_probe(struct ftrace_ops_hash *old_hash)
3736 ftrace_probe_registered = 1; 3736 ftrace_probe_registered = 1;
3737} 3737}
3738 3738
3739static void __disable_ftrace_function_probe(void) 3739static bool __disable_ftrace_function_probe(void)
3740{ 3740{
3741 int i; 3741 int i;
3742 3742
3743 if (!ftrace_probe_registered) 3743 if (!ftrace_probe_registered)
3744 return; 3744 return false;
3745 3745
3746 for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { 3746 for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
3747 struct hlist_head *hhd = &ftrace_func_hash[i]; 3747 struct hlist_head *hhd = &ftrace_func_hash[i];
3748 if (hhd->first) 3748 if (hhd->first)
3749 return; 3749 return false;
3750 } 3750 }
3751 3751
3752 /* no more funcs left */ 3752 /* no more funcs left */
3753 ftrace_shutdown(&trace_probe_ops, 0); 3753 ftrace_shutdown(&trace_probe_ops, 0);
3754 3754
3755 ftrace_probe_registered = 0; 3755 ftrace_probe_registered = 0;
3756 return true;
3756} 3757}
3757 3758
3758 3759
@@ -3882,6 +3883,7 @@ static void
3882__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, 3883__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3883 void *data, int flags) 3884 void *data, int flags)
3884{ 3885{
3886 struct ftrace_ops_hash old_hash_ops;
3885 struct ftrace_func_entry *rec_entry; 3887 struct ftrace_func_entry *rec_entry;
3886 struct ftrace_func_probe *entry; 3888 struct ftrace_func_probe *entry;
3887 struct ftrace_func_probe *p; 3889 struct ftrace_func_probe *p;
@@ -3893,6 +3895,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3893 struct hlist_node *tmp; 3895 struct hlist_node *tmp;
3894 char str[KSYM_SYMBOL_LEN]; 3896 char str[KSYM_SYMBOL_LEN];
3895 int i, ret; 3897 int i, ret;
3898 bool disabled;
3896 3899
3897 if (glob && (strcmp(glob, "*") == 0 || !strlen(glob))) 3900 if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
3898 func_g.search = NULL; 3901 func_g.search = NULL;
@@ -3911,6 +3914,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3911 3914
3912 mutex_lock(&trace_probe_ops.func_hash->regex_lock); 3915 mutex_lock(&trace_probe_ops.func_hash->regex_lock);
3913 3916
3917 old_hash_ops.filter_hash = old_hash;
3918 /* Probes only have filters */
3919 old_hash_ops.notrace_hash = NULL;
3920
3914 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); 3921 hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
3915 if (!hash) 3922 if (!hash)
3916 /* Hmm, should report this somehow */ 3923 /* Hmm, should report this somehow */
@@ -3948,12 +3955,17 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
3948 } 3955 }
3949 } 3956 }
3950 mutex_lock(&ftrace_lock); 3957 mutex_lock(&ftrace_lock);
3951 __disable_ftrace_function_probe(); 3958 disabled = __disable_ftrace_function_probe();
3952 /* 3959 /*
3953 * Remove after the disable is called. Otherwise, if the last 3960 * Remove after the disable is called. Otherwise, if the last
3954 * probe is removed, a null hash means *all enabled*. 3961 * probe is removed, a null hash means *all enabled*.
3955 */ 3962 */
3956 ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash); 3963 ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
3964
3965 /* still need to update the function call sites */
3966 if (ftrace_enabled && !disabled)
3967 ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS,
3968 &old_hash_ops);
3957 synchronize_sched(); 3969 synchronize_sched();
3958 if (!ret) 3970 if (!ret)
3959 free_ftrace_hash_rcu(old_hash); 3971 free_ftrace_hash_rcu(old_hash);