aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-12-16 14:42:37 -0500
committerSteven Rostedt <rostedt@goodmis.org>2011-12-21 07:17:57 -0500
commit3208230983a0ee3d95be22d463257e530c684956 (patch)
treefdba765e348c53a4fd65094ac17e66061f0b8932 /kernel/trace
parentc88fd8634ea68e74c7d19fd2621b4078fd22864c (diff)
ftrace: Remove usage of "freed" records
Records that are added to the function trace table are permanently there, except for modules. By separating out the modules to their own pages that can be freed in one shot we can remove the "freed" flag and simplify some of the record management. Another benefit of doing this is that we can also move the records around; sort them. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ftrace.c100
1 files changed, 49 insertions, 51 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 655b432fb890..be6888f40d2b 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -996,8 +996,6 @@ struct ftrace_page {
996static struct ftrace_page *ftrace_pages_start; 996static struct ftrace_page *ftrace_pages_start;
997static struct ftrace_page *ftrace_pages; 997static struct ftrace_page *ftrace_pages;
998 998
999static struct dyn_ftrace *ftrace_free_records;
1000
1001static struct ftrace_func_entry * 999static struct ftrace_func_entry *
1002ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip) 1000ftrace_lookup_ip(struct ftrace_hash *hash, unsigned long ip)
1003{ 1001{
@@ -1421,32 +1419,8 @@ static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
1421 __ftrace_hash_rec_update(ops, filter_hash, 1); 1419 __ftrace_hash_rec_update(ops, filter_hash, 1);
1422} 1420}
1423 1421
1424static void ftrace_free_rec(struct dyn_ftrace *rec)
1425{
1426 rec->freelist = ftrace_free_records;
1427 ftrace_free_records = rec;
1428 rec->flags |= FTRACE_FL_FREE;
1429}
1430
1431static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip) 1422static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
1432{ 1423{
1433 struct dyn_ftrace *rec;
1434
1435 /* First check for freed records */
1436 if (ftrace_free_records) {
1437 rec = ftrace_free_records;
1438
1439 if (unlikely(!(rec->flags & FTRACE_FL_FREE))) {
1440 FTRACE_WARN_ON_ONCE(1);
1441 ftrace_free_records = NULL;
1442 return NULL;
1443 }
1444
1445 ftrace_free_records = rec->freelist;
1446 memset(rec, 0, sizeof(*rec));
1447 return rec;
1448 }
1449
1450 if (ftrace_pages->index == ENTRIES_PER_PAGE) { 1424 if (ftrace_pages->index == ENTRIES_PER_PAGE) {
1451 if (!ftrace_pages->next) { 1425 if (!ftrace_pages->next) {
1452 /* allocate another page */ 1426 /* allocate another page */
@@ -1639,10 +1613,6 @@ static void ftrace_replace_code(int update)
1639 return; 1613 return;
1640 1614
1641 do_for_each_ftrace_rec(pg, rec) { 1615 do_for_each_ftrace_rec(pg, rec) {
1642 /* Skip over free records */
1643 if (rec->flags & FTRACE_FL_FREE)
1644 continue;
1645
1646 failed = __ftrace_replace_code(rec, update); 1616 failed = __ftrace_replace_code(rec, update);
1647 if (failed) { 1617 if (failed) {
1648 ftrace_bug(failed, rec->ip); 1618 ftrace_bug(failed, rec->ip);
@@ -2007,11 +1977,8 @@ static int ftrace_update_code(struct module *mod)
2007 * Do the initial record conversion from mcount jump 1977 * Do the initial record conversion from mcount jump
2008 * to the NOP instructions. 1978 * to the NOP instructions.
2009 */ 1979 */
2010 if (!ftrace_code_disable(mod, p)) { 1980 if (!ftrace_code_disable(mod, p))
2011 ftrace_free_rec(p);
2012 /* Game over */
2013 break; 1981 break;
2014 }
2015 1982
2016 ftrace_update_cnt++; 1983 ftrace_update_cnt++;
2017 1984
@@ -2026,10 +1993,8 @@ static int ftrace_update_code(struct module *mod)
2026 */ 1993 */
2027 if (ftrace_start_up && ref) { 1994 if (ftrace_start_up && ref) {
2028 int failed = __ftrace_replace_code(p, 1); 1995 int failed = __ftrace_replace_code(p, 1);
2029 if (failed) { 1996 if (failed)
2030 ftrace_bug(failed, p->ip); 1997 ftrace_bug(failed, p->ip);
2031 ftrace_free_rec(p);
2032 }
2033 } 1998 }
2034 } 1999 }
2035 2000
@@ -2223,9 +2188,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
2223 } 2188 }
2224 } else { 2189 } else {
2225 rec = &iter->pg->records[iter->idx++]; 2190 rec = &iter->pg->records[iter->idx++];
2226 if ((rec->flags & FTRACE_FL_FREE) || 2191 if (((iter->flags & FTRACE_ITER_FILTER) &&
2227
2228 ((iter->flags & FTRACE_ITER_FILTER) &&
2229 !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) || 2192 !(ftrace_lookup_ip(ops->filter_hash, rec->ip))) ||
2230 2193
2231 ((iter->flags & FTRACE_ITER_NOTRACE) && 2194 ((iter->flags & FTRACE_ITER_NOTRACE) &&
@@ -2602,7 +2565,6 @@ match_records(struct ftrace_hash *hash, char *buff,
2602 goto out_unlock; 2565 goto out_unlock;
2603 2566
2604 do_for_each_ftrace_rec(pg, rec) { 2567 do_for_each_ftrace_rec(pg, rec) {
2605
2606 if (ftrace_match_record(rec, mod, search, search_len, type)) { 2568 if (ftrace_match_record(rec, mod, search, search_len, type)) {
2607 ret = enter_record(hash, rec, not); 2569 ret = enter_record(hash, rec, not);
2608 if (ret < 0) { 2570 if (ret < 0) {
@@ -3446,9 +3408,6 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
3446 3408
3447 do_for_each_ftrace_rec(pg, rec) { 3409 do_for_each_ftrace_rec(pg, rec) {
3448 3410
3449 if (rec->flags & FTRACE_FL_FREE)
3450 continue;
3451
3452 if (ftrace_match_record(rec, NULL, search, search_len, type)) { 3411 if (ftrace_match_record(rec, NULL, search, search_len, type)) {
3453 /* if it is in the array */ 3412 /* if it is in the array */
3454 exists = false; 3413 exists = false;
@@ -3566,6 +3525,27 @@ static int ftrace_process_locs(struct module *mod,
3566 unsigned long flags = 0; /* Shut up gcc */ 3525 unsigned long flags = 0; /* Shut up gcc */
3567 3526
3568 mutex_lock(&ftrace_lock); 3527 mutex_lock(&ftrace_lock);
3528 /*
3529 * Core and each module needs their own pages, as
3530 * modules will free them when they are removed.
3531 * Force a new page to be allocated for modules.
3532 */
3533 if (mod) {
3534 if (!ftrace_pages)
3535 return -ENOMEM;
3536
3537 /*
3538 * If the last page was full, it will be
3539 * allocated anyway.
3540 */
3541 if (ftrace_pages->index != ENTRIES_PER_PAGE) {
3542 ftrace_pages->next = (void *)get_zeroed_page(GFP_KERNEL);
3543 if (!ftrace_pages->next)
3544 return -ENOMEM;
3545 ftrace_pages = ftrace_pages->next;
3546 }
3547 }
3548
3569 p = start; 3549 p = start;
3570 while (p < end) { 3550 while (p < end) {
3571 addr = ftrace_call_adjust(*p++); 3551 addr = ftrace_call_adjust(*p++);
@@ -3599,9 +3579,13 @@ static int ftrace_process_locs(struct module *mod,
3599} 3579}
3600 3580
3601#ifdef CONFIG_MODULES 3581#ifdef CONFIG_MODULES
3582
3583#define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)
3584
3602void ftrace_release_mod(struct module *mod) 3585void ftrace_release_mod(struct module *mod)
3603{ 3586{
3604 struct dyn_ftrace *rec; 3587 struct dyn_ftrace *rec;
3588 struct ftrace_page **last_pg;
3605 struct ftrace_page *pg; 3589 struct ftrace_page *pg;
3606 3590
3607 mutex_lock(&ftrace_lock); 3591 mutex_lock(&ftrace_lock);
@@ -3609,16 +3593,30 @@ void ftrace_release_mod(struct module *mod)
3609 if (ftrace_disabled) 3593 if (ftrace_disabled)
3610 goto out_unlock; 3594 goto out_unlock;
3611 3595
3612 do_for_each_ftrace_rec(pg, rec) { 3596 /*
3597 * Each module has its own ftrace_pages, remove
3598 * them from the list.
3599 */
3600 last_pg = &ftrace_pages_start;
3601 for (pg = ftrace_pages_start; pg; pg = *last_pg) {
3602 rec = &pg->records[0];
3613 if (within_module_core(rec->ip, mod)) { 3603 if (within_module_core(rec->ip, mod)) {
3614 /* 3604 /*
3615 * rec->ip is changed in ftrace_free_rec() 3605 * As core pages are first, the first
3616 * It should not between s and e if record was freed. 3606 * page should never be a module page.
3617 */ 3607 */
3618 FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE); 3608 if (WARN_ON(pg == ftrace_pages_start))
3619 ftrace_free_rec(rec); 3609 goto out_unlock;
3620 } 3610
3621 } while_for_each_ftrace_rec(); 3611 /* Check if we are deleting the last page */
3612 if (pg == ftrace_pages)
3613 ftrace_pages = next_to_ftrace_page(last_pg);
3614
3615 *last_pg = pg->next;
3616 free_page((unsigned long)pg);
3617 } else
3618 last_pg = &pg->next;
3619 }
3622 out_unlock: 3620 out_unlock:
3623 mutex_unlock(&ftrace_lock); 3621 mutex_unlock(&ftrace_lock);
3624} 3622}