aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/ftrace.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 37f9e90d241c..92376aeac4a7 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1507,25 +1507,38 @@ static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
1507static void ftrace_remove_tramp(struct ftrace_ops *ops, 1507static void ftrace_remove_tramp(struct ftrace_ops *ops,
1508 struct dyn_ftrace *rec) 1508 struct dyn_ftrace *rec)
1509{ 1509{
1510 struct ftrace_func_entry *entry; 1510 /* If TRAMP is not set, no ops should have a trampoline for this */
1511 1511 if (!(rec->flags & FTRACE_FL_TRAMP))
1512 entry = ftrace_lookup_ip(ops->tramp_hash, rec->ip);
1513 if (!entry)
1514 return; 1512 return;
1515 1513
1514 rec->flags &= ~FTRACE_FL_TRAMP;
1515
1516 if ((!ftrace_hash_empty(ops->func_hash->filter_hash) &&
1517 !ftrace_lookup_ip(ops->func_hash->filter_hash, rec->ip)) ||
1518 ftrace_lookup_ip(ops->func_hash->notrace_hash, rec->ip))
1519 return;
1516 /* 1520 /*
1517 * The tramp_hash entry will be removed at time 1521 * The tramp_hash entry will be removed at time
1518 * of update. 1522 * of update.
1519 */ 1523 */
1520 ops->nr_trampolines--; 1524 ops->nr_trampolines--;
1521 rec->flags &= ~FTRACE_FL_TRAMP;
1522} 1525}
1523 1526
1524static void ftrace_clear_tramps(struct dyn_ftrace *rec) 1527static void ftrace_clear_tramps(struct dyn_ftrace *rec, struct ftrace_ops *ops)
1525{ 1528{
1526 struct ftrace_ops *op; 1529 struct ftrace_ops *op;
1527 1530
1531 /* If TRAMP is not set, no ops should have a trampoline for this */
1532 if (!(rec->flags & FTRACE_FL_TRAMP))
1533 return;
1534
1528 do_for_each_ftrace_op(op, ftrace_ops_list) { 1535 do_for_each_ftrace_op(op, ftrace_ops_list) {
1536 /*
1537 * This function is called to clear other tramps
1538 * not the one that is being updated.
1539 */
1540 if (op == ops)
1541 continue;
1529 if (op->nr_trampolines) 1542 if (op->nr_trampolines)
1530 ftrace_remove_tramp(op, rec); 1543 ftrace_remove_tramp(op, rec);
1531 } while_for_each_ftrace_op(op); 1544 } while_for_each_ftrace_op(op);
@@ -1626,13 +1639,10 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
1626 /* 1639 /*
1627 * If we are adding another function callback 1640 * If we are adding another function callback
1628 * to this function, and the previous had a 1641 * to this function, and the previous had a
1629 * trampoline used, then we need to go back to 1642 * custom trampoline in use, then we need to go
1630 * the default trampoline. 1643 * back to the default trampoline.
1631 */ 1644 */
1632 rec->flags &= ~FTRACE_FL_TRAMP; 1645 ftrace_clear_tramps(rec, ops);
1633
1634 /* remove trampolines from any ops for this rec */
1635 ftrace_clear_tramps(rec);
1636 } 1646 }
1637 1647
1638 /* 1648 /*
@@ -1935,8 +1945,8 @@ unsigned long ftrace_get_addr_new(struct dyn_ftrace *rec)
1935 if (rec->flags & FTRACE_FL_TRAMP) { 1945 if (rec->flags & FTRACE_FL_TRAMP) {
1936 ops = ftrace_find_tramp_ops_new(rec); 1946 ops = ftrace_find_tramp_ops_new(rec);
1937 if (FTRACE_WARN_ON(!ops || !ops->trampoline)) { 1947 if (FTRACE_WARN_ON(!ops || !ops->trampoline)) {
1938 pr_warning("Bad trampoline accounting at: %p (%pS)\n", 1948 pr_warn("Bad trampoline accounting at: %p (%pS) (%lx)\n",
1939 (void *)rec->ip, (void *)rec->ip); 1949 (void *)rec->ip, (void *)rec->ip, rec->flags);
1940 /* Ftrace is shutting down, return anything */ 1950 /* Ftrace is shutting down, return anything */
1941 return (unsigned long)FTRACE_ADDR; 1951 return (unsigned long)FTRACE_ADDR;
1942 } 1952 }
@@ -2266,7 +2276,10 @@ static int ftrace_save_ops_tramp_hash(struct ftrace_ops *ops)
2266 } while_for_each_ftrace_rec(); 2276 } while_for_each_ftrace_rec();
2267 2277
2268 /* The number of recs in the hash must match nr_trampolines */ 2278 /* The number of recs in the hash must match nr_trampolines */
2269 FTRACE_WARN_ON(ops->tramp_hash->count != ops->nr_trampolines); 2279 if (FTRACE_WARN_ON(ops->tramp_hash->count != ops->nr_trampolines))
2280 pr_warn("count=%ld trampolines=%d\n",
2281 ops->tramp_hash->count,
2282 ops->nr_trampolines);
2270 2283
2271 return 0; 2284 return 0;
2272} 2285}