aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c101
1 files changed, 61 insertions, 40 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 3718d55fb4c3..25edd5cc5935 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)
@@ -766,7 +768,7 @@ static struct tracer_stat function_stats __initdata = {
766 .stat_show = function_stat_show 768 .stat_show = function_stat_show
767}; 769};
768 770
769static void ftrace_profile_debugfs(struct dentry *d_tracer) 771static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
770{ 772{
771 struct ftrace_profile_stat *stat; 773 struct ftrace_profile_stat *stat;
772 struct dentry *entry; 774 struct dentry *entry;
@@ -784,7 +786,6 @@ static void ftrace_profile_debugfs(struct dentry *d_tracer)
784 * The files created are permanent, if something happens 786 * The files created are permanent, if something happens
785 * we still do not free memory. 787 * we still do not free memory.
786 */ 788 */
787 kfree(stat);
788 WARN(1, 789 WARN(1,
789 "Could not allocate stat file for cpu %d\n", 790 "Could not allocate stat file for cpu %d\n",
790 cpu); 791 cpu);
@@ -811,7 +812,7 @@ static void ftrace_profile_debugfs(struct dentry *d_tracer)
811} 812}
812 813
813#else /* CONFIG_FUNCTION_PROFILER */ 814#else /* CONFIG_FUNCTION_PROFILER */
814static void ftrace_profile_debugfs(struct dentry *d_tracer) 815static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
815{ 816{
816} 817}
817#endif /* CONFIG_FUNCTION_PROFILER */ 818#endif /* CONFIG_FUNCTION_PROFILER */
@@ -1417,10 +1418,20 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos)
1417{ 1418{
1418 struct ftrace_iterator *iter = m->private; 1419 struct ftrace_iterator *iter = m->private;
1419 void *p = NULL; 1420 void *p = NULL;
1421 loff_t l;
1422
1423 if (!(iter->flags & FTRACE_ITER_HASH))
1424 *pos = 0;
1420 1425
1421 iter->flags |= FTRACE_ITER_HASH; 1426 iter->flags |= FTRACE_ITER_HASH;
1422 1427
1423 return t_hash_next(m, p, pos); 1428 iter->hidx = 0;
1429 for (l = 0; l <= *pos; ) {
1430 p = t_hash_next(m, p, &l);
1431 if (!p)
1432 break;
1433 }
1434 return p;
1424} 1435}
1425 1436
1426static int t_hash_show(struct seq_file *m, void *v) 1437static int t_hash_show(struct seq_file *m, void *v)
@@ -1467,8 +1478,6 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
1467 iter->pg = iter->pg->next; 1478 iter->pg = iter->pg->next;
1468 iter->idx = 0; 1479 iter->idx = 0;
1469 goto retry; 1480 goto retry;
1470 } else {
1471 iter->idx = -1;
1472 } 1481 }
1473 } else { 1482 } else {
1474 rec = &iter->pg->records[iter->idx++]; 1483 rec = &iter->pg->records[iter->idx++];
@@ -1497,6 +1506,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1497{ 1506{
1498 struct ftrace_iterator *iter = m->private; 1507 struct ftrace_iterator *iter = m->private;
1499 void *p = NULL; 1508 void *p = NULL;
1509 loff_t l;
1500 1510
1501 mutex_lock(&ftrace_lock); 1511 mutex_lock(&ftrace_lock);
1502 /* 1512 /*
@@ -1508,23 +1518,21 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1508 if (*pos > 0) 1518 if (*pos > 0)
1509 return t_hash_start(m, pos); 1519 return t_hash_start(m, pos);
1510 iter->flags |= FTRACE_ITER_PRINTALL; 1520 iter->flags |= FTRACE_ITER_PRINTALL;
1511 (*pos)++;
1512 return iter; 1521 return iter;
1513 } 1522 }
1514 1523
1515 if (iter->flags & FTRACE_ITER_HASH) 1524 if (iter->flags & FTRACE_ITER_HASH)
1516 return t_hash_start(m, pos); 1525 return t_hash_start(m, pos);
1517 1526
1518 if (*pos > 0) { 1527 iter->pg = ftrace_pages_start;
1519 if (iter->idx < 0) 1528 iter->idx = 0;
1520 return p; 1529 for (l = 0; l <= *pos; ) {
1521 (*pos)--; 1530 p = t_next(m, p, &l);
1522 iter->idx--; 1531 if (!p)
1532 break;
1523 } 1533 }
1524 1534
1525 p = t_next(m, p, pos); 1535 if (!p && iter->flags & FTRACE_ITER_FILTER)
1526
1527 if (!p)
1528 return t_hash_start(m, pos); 1536 return t_hash_start(m, pos);
1529 1537
1530 return p; 1538 return p;
@@ -1654,7 +1662,7 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
1654 1662
1655 mutex_lock(&ftrace_regex_lock); 1663 mutex_lock(&ftrace_regex_lock);
1656 if ((file->f_mode & FMODE_WRITE) && 1664 if ((file->f_mode & FMODE_WRITE) &&
1657 !(file->f_flags & O_APPEND)) 1665 (file->f_flags & O_TRUNC))
1658 ftrace_filter_reset(enable); 1666 ftrace_filter_reset(enable);
1659 1667
1660 if (file->f_mode & FMODE_READ) { 1668 if (file->f_mode & FMODE_READ) {
@@ -2270,7 +2278,11 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
2270 read++; 2278 read++;
2271 cnt--; 2279 cnt--;
2272 2280
2273 if (!(iter->flags & ~FTRACE_ITER_CONT)) { 2281 /*
2282 * If the parser haven't finished with the last write,
2283 * continue reading the user input without skipping spaces.
2284 */
2285 if (!(iter->flags & FTRACE_ITER_CONT)) {
2274 /* skip white space */ 2286 /* skip white space */
2275 while (cnt && isspace(ch)) { 2287 while (cnt && isspace(ch)) {
2276 ret = get_user(ch, ubuf++); 2288 ret = get_user(ch, ubuf++);
@@ -2280,8 +2292,9 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
2280 cnt--; 2292 cnt--;
2281 } 2293 }
2282 2294
2295 /* only spaces were written */
2283 if (isspace(ch)) { 2296 if (isspace(ch)) {
2284 file->f_pos += read; 2297 *ppos += read;
2285 ret = read; 2298 ret = read;
2286 goto out; 2299 goto out;
2287 } 2300 }
@@ -2311,12 +2324,12 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
2311 if (ret) 2324 if (ret)
2312 goto out; 2325 goto out;
2313 iter->buffer_idx = 0; 2326 iter->buffer_idx = 0;
2314 } else 2327 } else {
2315 iter->flags |= FTRACE_ITER_CONT; 2328 iter->flags |= FTRACE_ITER_CONT;
2329 iter->buffer[iter->buffer_idx++] = ch;
2330 }
2316 2331
2317 2332 *ppos += read;
2318 file->f_pos += read;
2319
2320 ret = read; 2333 ret = read;
2321 out: 2334 out:
2322 mutex_unlock(&ftrace_regex_lock); 2335 mutex_unlock(&ftrace_regex_lock);
@@ -2500,32 +2513,31 @@ int ftrace_graph_count;
2500unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; 2513unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
2501 2514
2502static void * 2515static void *
2503g_next(struct seq_file *m, void *v, loff_t *pos) 2516__g_next(struct seq_file *m, loff_t *pos)
2504{ 2517{
2505 unsigned long *array = m->private; 2518 unsigned long *array = m->private;
2506 int index = *pos;
2507 2519
2508 (*pos)++; 2520 if (*pos >= ftrace_graph_count)
2509
2510 if (index >= ftrace_graph_count)
2511 return NULL; 2521 return NULL;
2522 return &array[*pos];
2523}
2512 2524
2513 return &array[index]; 2525static void *
2526g_next(struct seq_file *m, void *v, loff_t *pos)
2527{
2528 (*pos)++;
2529 return __g_next(m, pos);
2514} 2530}
2515 2531
2516static void *g_start(struct seq_file *m, loff_t *pos) 2532static void *g_start(struct seq_file *m, loff_t *pos)
2517{ 2533{
2518 void *p = NULL;
2519
2520 mutex_lock(&graph_lock); 2534 mutex_lock(&graph_lock);
2521 2535
2522 /* Nothing, tell g_show to print all functions are enabled */ 2536 /* Nothing, tell g_show to print all functions are enabled */
2523 if (!ftrace_graph_count && !*pos) 2537 if (!ftrace_graph_count && !*pos)
2524 return (void *)1; 2538 return (void *)1;
2525 2539
2526 p = g_next(m, p, pos); 2540 return __g_next(m, pos);
2527
2528 return p;
2529} 2541}
2530 2542
2531static void g_stop(struct seq_file *m, void *p) 2543static void g_stop(struct seq_file *m, void *p)
@@ -2570,7 +2582,7 @@ ftrace_graph_open(struct inode *inode, struct file *file)
2570 2582
2571 mutex_lock(&graph_lock); 2583 mutex_lock(&graph_lock);
2572 if ((file->f_mode & FMODE_WRITE) && 2584 if ((file->f_mode & FMODE_WRITE) &&
2573 !(file->f_flags & O_APPEND)) { 2585 (file->f_flags & O_TRUNC)) {
2574 ftrace_graph_count = 0; 2586 ftrace_graph_count = 0;
2575 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs)); 2587 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
2576 } 2588 }
@@ -2589,6 +2601,14 @@ ftrace_graph_open(struct inode *inode, struct file *file)
2589} 2601}
2590 2602
2591static int 2603static int
2604ftrace_graph_release(struct inode *inode, struct file *file)
2605{
2606 if (file->f_mode & FMODE_READ)
2607 seq_release(inode, file);
2608 return 0;
2609}
2610
2611static int
2592ftrace_set_func(unsigned long *array, int *idx, char *buffer) 2612ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2593{ 2613{
2594 struct dyn_ftrace *rec; 2614 struct dyn_ftrace *rec;
@@ -2717,9 +2737,10 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
2717} 2737}
2718 2738
2719static const struct file_operations ftrace_graph_fops = { 2739static const struct file_operations ftrace_graph_fops = {
2720 .open = ftrace_graph_open, 2740 .open = ftrace_graph_open,
2721 .read = seq_read, 2741 .read = seq_read,
2722 .write = ftrace_graph_write, 2742 .write = ftrace_graph_write,
2743 .release = ftrace_graph_release,
2723}; 2744};
2724#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 2745#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2725 2746
@@ -3152,10 +3173,10 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
3152 3173
3153 ret = proc_dointvec(table, write, file, buffer, lenp, ppos); 3174 ret = proc_dointvec(table, write, file, buffer, lenp, ppos);
3154 3175
3155 if (ret || !write || (last_ftrace_enabled == ftrace_enabled)) 3176 if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
3156 goto out; 3177 goto out;
3157 3178
3158 last_ftrace_enabled = ftrace_enabled; 3179 last_ftrace_enabled = !!ftrace_enabled;
3159 3180
3160 if (ftrace_enabled) { 3181 if (ftrace_enabled) {
3161 3182