diff options
Diffstat (limited to 'kernel')
-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 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 | ||
3739 | static void __disable_ftrace_function_probe(void) | 3739 | static 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); |