diff options
Diffstat (limited to 'kernel/trace/ftrace.c')
| -rw-r--r-- | kernel/trace/ftrace.c | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3718d55fb4c3..f3716bf04df6 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -291,7 +291,9 @@ function_stat_next(void *v, int idx) | |||
| 291 | pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK); | 291 | pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK); |
| 292 | 292 | ||
| 293 | again: | 293 | again: |
| 294 | rec++; | 294 | if (idx != 0) |
| 295 | rec++; | ||
| 296 | |||
| 295 | if ((void *)rec >= (void *)&pg->records[pg->index]) { | 297 | if ((void *)rec >= (void *)&pg->records[pg->index]) { |
| 296 | pg = pg->next; | 298 | pg = pg->next; |
| 297 | if (!pg) | 299 | if (!pg) |
| @@ -1417,10 +1419,20 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos) | |||
| 1417 | { | 1419 | { |
| 1418 | struct ftrace_iterator *iter = m->private; | 1420 | struct ftrace_iterator *iter = m->private; |
| 1419 | void *p = NULL; | 1421 | void *p = NULL; |
| 1422 | loff_t l; | ||
| 1423 | |||
| 1424 | if (!(iter->flags & FTRACE_ITER_HASH)) | ||
| 1425 | *pos = 0; | ||
| 1420 | 1426 | ||
| 1421 | iter->flags |= FTRACE_ITER_HASH; | 1427 | iter->flags |= FTRACE_ITER_HASH; |
| 1422 | 1428 | ||
| 1423 | return t_hash_next(m, p, pos); | 1429 | iter->hidx = 0; |
| 1430 | for (l = 0; l <= *pos; ) { | ||
| 1431 | p = t_hash_next(m, p, &l); | ||
| 1432 | if (!p) | ||
| 1433 | break; | ||
| 1434 | } | ||
| 1435 | return p; | ||
| 1424 | } | 1436 | } |
| 1425 | 1437 | ||
| 1426 | static int t_hash_show(struct seq_file *m, void *v) | 1438 | static int t_hash_show(struct seq_file *m, void *v) |
| @@ -1467,8 +1479,6 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 1467 | iter->pg = iter->pg->next; | 1479 | iter->pg = iter->pg->next; |
| 1468 | iter->idx = 0; | 1480 | iter->idx = 0; |
| 1469 | goto retry; | 1481 | goto retry; |
| 1470 | } else { | ||
| 1471 | iter->idx = -1; | ||
| 1472 | } | 1482 | } |
| 1473 | } else { | 1483 | } else { |
| 1474 | rec = &iter->pg->records[iter->idx++]; | 1484 | rec = &iter->pg->records[iter->idx++]; |
| @@ -1497,6 +1507,7 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
| 1497 | { | 1507 | { |
| 1498 | struct ftrace_iterator *iter = m->private; | 1508 | struct ftrace_iterator *iter = m->private; |
| 1499 | void *p = NULL; | 1509 | void *p = NULL; |
| 1510 | loff_t l; | ||
| 1500 | 1511 | ||
| 1501 | mutex_lock(&ftrace_lock); | 1512 | mutex_lock(&ftrace_lock); |
| 1502 | /* | 1513 | /* |
| @@ -1508,23 +1519,21 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
| 1508 | if (*pos > 0) | 1519 | if (*pos > 0) |
| 1509 | return t_hash_start(m, pos); | 1520 | return t_hash_start(m, pos); |
| 1510 | iter->flags |= FTRACE_ITER_PRINTALL; | 1521 | iter->flags |= FTRACE_ITER_PRINTALL; |
| 1511 | (*pos)++; | ||
| 1512 | return iter; | 1522 | return iter; |
| 1513 | } | 1523 | } |
| 1514 | 1524 | ||
| 1515 | if (iter->flags & FTRACE_ITER_HASH) | 1525 | if (iter->flags & FTRACE_ITER_HASH) |
| 1516 | return t_hash_start(m, pos); | 1526 | return t_hash_start(m, pos); |
| 1517 | 1527 | ||
| 1518 | if (*pos > 0) { | 1528 | iter->pg = ftrace_pages_start; |
| 1519 | if (iter->idx < 0) | 1529 | iter->idx = 0; |
| 1520 | return p; | 1530 | for (l = 0; l <= *pos; ) { |
| 1521 | (*pos)--; | 1531 | p = t_next(m, p, &l); |
| 1522 | iter->idx--; | 1532 | if (!p) |
| 1533 | break; | ||
| 1523 | } | 1534 | } |
| 1524 | 1535 | ||
| 1525 | p = t_next(m, p, pos); | 1536 | if (!p && iter->flags & FTRACE_ITER_FILTER) |
| 1526 | |||
| 1527 | if (!p) | ||
| 1528 | return t_hash_start(m, pos); | 1537 | return t_hash_start(m, pos); |
| 1529 | 1538 | ||
| 1530 | return p; | 1539 | return p; |
| @@ -2500,32 +2509,31 @@ int ftrace_graph_count; | |||
| 2500 | unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; | 2509 | unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; |
| 2501 | 2510 | ||
| 2502 | static void * | 2511 | static void * |
| 2503 | g_next(struct seq_file *m, void *v, loff_t *pos) | 2512 | __g_next(struct seq_file *m, loff_t *pos) |
| 2504 | { | 2513 | { |
| 2505 | unsigned long *array = m->private; | 2514 | unsigned long *array = m->private; |
| 2506 | int index = *pos; | ||
| 2507 | 2515 | ||
| 2508 | (*pos)++; | 2516 | if (*pos >= ftrace_graph_count) |
| 2509 | |||
| 2510 | if (index >= ftrace_graph_count) | ||
| 2511 | return NULL; | 2517 | return NULL; |
| 2518 | return &array[*pos]; | ||
| 2519 | } | ||
| 2512 | 2520 | ||
| 2513 | return &array[index]; | 2521 | static void * |
| 2522 | g_next(struct seq_file *m, void *v, loff_t *pos) | ||
| 2523 | { | ||
| 2524 | (*pos)++; | ||
| 2525 | return __g_next(m, pos); | ||
| 2514 | } | 2526 | } |
| 2515 | 2527 | ||
| 2516 | static void *g_start(struct seq_file *m, loff_t *pos) | 2528 | static void *g_start(struct seq_file *m, loff_t *pos) |
| 2517 | { | 2529 | { |
| 2518 | void *p = NULL; | ||
| 2519 | |||
| 2520 | mutex_lock(&graph_lock); | 2530 | mutex_lock(&graph_lock); |
| 2521 | 2531 | ||
| 2522 | /* Nothing, tell g_show to print all functions are enabled */ | 2532 | /* Nothing, tell g_show to print all functions are enabled */ |
| 2523 | if (!ftrace_graph_count && !*pos) | 2533 | if (!ftrace_graph_count && !*pos) |
| 2524 | return (void *)1; | 2534 | return (void *)1; |
| 2525 | 2535 | ||
| 2526 | p = g_next(m, p, pos); | 2536 | return __g_next(m, pos); |
| 2527 | |||
| 2528 | return p; | ||
| 2529 | } | 2537 | } |
| 2530 | 2538 | ||
| 2531 | static void g_stop(struct seq_file *m, void *p) | 2539 | static void g_stop(struct seq_file *m, void *p) |
