|
@@ -3755,23 +3755,24 @@ static void __enable_ftrace_function_probe(struct ftrace_ops_hash *old_hash)
|
|
|
ftrace_probe_registered = 1;
|
|
|
}
|
|
|
|
|
|
-static void __disable_ftrace_function_probe(void)
|
|
|
+static bool __disable_ftrace_function_probe(void)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
if (!ftrace_probe_registered)
|
|
|
- return;
|
|
|
+ return false;
|
|
|
|
|
|
for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
|
|
|
struct hlist_head *hhd = &ftrace_func_hash[i];
|
|
|
if (hhd->first)
|
|
|
- return;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
/* no more funcs left */
|
|
|
ftrace_shutdown(&trace_probe_ops, 0);
|
|
|
|
|
|
ftrace_probe_registered = 0;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -3901,6 +3902,7 @@ static void
|
|
|
__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
|
|
|
void *data, int flags)
|
|
|
{
|
|
|
+ struct ftrace_ops_hash old_hash_ops;
|
|
|
struct ftrace_func_entry *rec_entry;
|
|
|
struct ftrace_func_probe *entry;
|
|
|
struct ftrace_func_probe *p;
|
|
@@ -3912,6 +3914,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
|
|
|
struct hlist_node *tmp;
|
|
|
char str[KSYM_SYMBOL_LEN];
|
|
|
int i, ret;
|
|
|
+ bool disabled;
|
|
|
|
|
|
if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
|
|
|
func_g.search = NULL;
|
|
@@ -3930,6 +3933,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
|
|
|
|
|
|
mutex_lock(&trace_probe_ops.func_hash->regex_lock);
|
|
|
|
|
|
+ old_hash_ops.filter_hash = old_hash;
|
|
|
+ /* Probes only have filters */
|
|
|
+ old_hash_ops.notrace_hash = NULL;
|
|
|
+
|
|
|
hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
|
|
|
if (!hash)
|
|
|
/* Hmm, should report this somehow */
|
|
@@ -3967,12 +3974,17 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
|
|
|
}
|
|
|
}
|
|
|
mutex_lock(&ftrace_lock);
|
|
|
- __disable_ftrace_function_probe();
|
|
|
+ disabled = __disable_ftrace_function_probe();
|
|
|
/*
|
|
|
* Remove after the disable is called. Otherwise, if the last
|
|
|
* probe is removed, a null hash means *all enabled*.
|
|
|
*/
|
|
|
ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
|
|
|
+
|
|
|
+ /* still need to update the function call sites */
|
|
|
+ if (ftrace_enabled && !disabled)
|
|
|
+ ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS,
|
|
|
+ &old_hash_ops);
|
|
|
synchronize_sched();
|
|
|
if (!ret)
|
|
|
free_ftrace_hash_rcu(old_hash);
|