Skip to content

Commit 4853886

Browse files
committed
Merge tag 'trace-v4.11-rc5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull ftrace fix from Steven Rostedt: "While rewriting the function probe code, I stumbled over a long standing bug. This bug has been there sinc function tracing was added way back when. But my new development depends on this bug being fixed, and it should be fixed regardless as it causes ftrace to disable itself when triggered, and a reboot is required to enable it again. The bug is that the function probe does not disable itself properly if there's another probe of its type still enabled. For example: # cd /sys/kernel/debug/tracing # echo schedule:traceoff > set_ftrace_filter # echo do_IRQ:traceoff > set_ftrace_filter # echo \!do_IRQ:traceoff > /debug/tracing/set_ftrace_filter # echo do_IRQ:traceoff > set_ftrace_filter The above registers two traceoff probes (one for schedule and one for do_IRQ, and then removes do_IRQ. But since there still exists one for schedule, it is not done properly. When adding do_IRQ back, the breakage in the accounting is noticed by the ftrace self tests, and it causes a warning and disables ftrace" * tag 'trace-v4.11-rc5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: ftrace: Fix removing of second function probe
2 parents d5ff081 + 82cc4fc commit 4853886

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

kernel/trace/ftrace.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3755,23 +3755,24 @@ static void __enable_ftrace_function_probe(struct ftrace_ops_hash *old_hash)
37553755
ftrace_probe_registered = 1;
37563756
}
37573757

3758-
static void __disable_ftrace_function_probe(void)
3758+
static bool __disable_ftrace_function_probe(void)
37593759
{
37603760
int i;
37613761

37623762
if (!ftrace_probe_registered)
3763-
return;
3763+
return false;
37643764

37653765
for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
37663766
struct hlist_head *hhd = &ftrace_func_hash[i];
37673767
if (hhd->first)
3768-
return;
3768+
return false;
37693769
}
37703770

37713771
/* no more funcs left */
37723772
ftrace_shutdown(&trace_probe_ops, 0);
37733773

37743774
ftrace_probe_registered = 0;
3775+
return true;
37753776
}
37763777

37773778

@@ -3901,6 +3902,7 @@ static void
39013902
__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
39023903
void *data, int flags)
39033904
{
3905+
struct ftrace_ops_hash old_hash_ops;
39043906
struct ftrace_func_entry *rec_entry;
39053907
struct ftrace_func_probe *entry;
39063908
struct ftrace_func_probe *p;
@@ -3912,6 +3914,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
39123914
struct hlist_node *tmp;
39133915
char str[KSYM_SYMBOL_LEN];
39143916
int i, ret;
3917+
bool disabled;
39153918

39163919
if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
39173920
func_g.search = NULL;
@@ -3930,6 +3933,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
39303933

39313934
mutex_lock(&trace_probe_ops.func_hash->regex_lock);
39323935

3936+
old_hash_ops.filter_hash = old_hash;
3937+
/* Probes only have filters */
3938+
old_hash_ops.notrace_hash = NULL;
3939+
39333940
hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
39343941
if (!hash)
39353942
/* Hmm, should report this somehow */
@@ -3967,12 +3974,17 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
39673974
}
39683975
}
39693976
mutex_lock(&ftrace_lock);
3970-
__disable_ftrace_function_probe();
3977+
disabled = __disable_ftrace_function_probe();
39713978
/*
39723979
* Remove after the disable is called. Otherwise, if the last
39733980
* probe is removed, a null hash means *all enabled*.
39743981
*/
39753982
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);
39763988
synchronize_sched();
39773989
if (!ret)
39783990
free_ftrace_hash_rcu(old_hash);

0 commit comments

Comments
 (0)