Skip to content

Commit 4c75b0f

Browse files
rnavrostedt
authored andcommitted
ftrace: Fix updating FTRACE_FL_TRAMP
On powerpc, kprobe-direct.tc triggered FTRACE_WARN_ON() in ftrace_get_addr_new() followed by the below message: Bad trampoline accounting at: 000000004222522f (wake_up_process+0xc/0x20) (f0000001) The set of steps leading to this involved: - modprobe ftrace-direct-too - enable_probe - modprobe ftrace-direct - rmmod ftrace-direct <-- trigger The problem turned out to be that we were not updating flags in the ftrace record properly. From the above message about the trampoline accounting being bad, it can be seen that the ftrace record still has FTRACE_FL_TRAMP set though ftrace-direct module is going away. This happens because we are checking if any ftrace_ops has the FTRACE_FL_TRAMP flag set _before_ updating the filter hash. The fix for this is to look for any _other_ ftrace_ops that also needs FTRACE_FL_TRAMP. Link: https://lkml.kernel.org/r/56c113aa9c3e10c19144a36d9684c7882bf09af5.1606412433.git.naveen.n.rao@linux.vnet.ibm.com Cc: [email protected] Fixes: a124692 ("ftrace: Enable trampoline when rec count returns back to one") Signed-off-by: Naveen N. Rao <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 8fa655a commit 4c75b0f

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

kernel/trace/ftrace.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,8 @@ static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
16291629
static struct ftrace_ops *
16301630
ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
16311631
static struct ftrace_ops *
1632+
ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude);
1633+
static struct ftrace_ops *
16321634
ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
16331635

16341636
static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
@@ -1778,7 +1780,7 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
17781780
* to it.
17791781
*/
17801782
if (ftrace_rec_count(rec) == 1 &&
1781-
ftrace_find_tramp_ops_any(rec))
1783+
ftrace_find_tramp_ops_any_other(rec, ops))
17821784
rec->flags |= FTRACE_FL_TRAMP;
17831785
else
17841786
rec->flags &= ~FTRACE_FL_TRAMP;
@@ -2244,6 +2246,24 @@ ftrace_find_tramp_ops_any(struct dyn_ftrace *rec)
22442246
return NULL;
22452247
}
22462248

2249+
static struct ftrace_ops *
2250+
ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude)
2251+
{
2252+
struct ftrace_ops *op;
2253+
unsigned long ip = rec->ip;
2254+
2255+
do_for_each_ftrace_op(op, ftrace_ops_list) {
2256+
2257+
if (op == op_exclude || !op->trampoline)
2258+
continue;
2259+
2260+
if (hash_contains_ip(ip, op->func_hash))
2261+
return op;
2262+
} while_for_each_ftrace_op(op);
2263+
2264+
return NULL;
2265+
}
2266+
22472267
static struct ftrace_ops *
22482268
ftrace_find_tramp_ops_next(struct dyn_ftrace *rec,
22492269
struct ftrace_ops *op)

0 commit comments

Comments
 (0)