diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/ftrace.c | 20 |
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 | ||
3758 | static void __disable_ftrace_function_probe(void) | 3758 | static 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); |