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.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 1e6640f80454..d996353473fd 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2426,6 +2426,7 @@ static const struct file_operations ftrace_notrace_fops = {
2426static DEFINE_MUTEX(graph_lock); 2426static DEFINE_MUTEX(graph_lock);
2427 2427
2428int ftrace_graph_count; 2428int ftrace_graph_count;
2429int ftrace_graph_filter_enabled;
2429unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; 2430unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
2430 2431
2431static void * 2432static void *
@@ -2448,7 +2449,7 @@ static void *g_start(struct seq_file *m, loff_t *pos)
2448 mutex_lock(&graph_lock); 2449 mutex_lock(&graph_lock);
2449 2450
2450 /* Nothing, tell g_show to print all functions are enabled */ 2451 /* Nothing, tell g_show to print all functions are enabled */
2451 if (!ftrace_graph_count && !*pos) 2452 if (!ftrace_graph_filter_enabled && !*pos)
2452 return (void *)1; 2453 return (void *)1;
2453 2454
2454 return __g_next(m, pos); 2455 return __g_next(m, pos);
@@ -2494,6 +2495,7 @@ ftrace_graph_open(struct inode *inode, struct file *file)
2494 mutex_lock(&graph_lock); 2495 mutex_lock(&graph_lock);
2495 if ((file->f_mode & FMODE_WRITE) && 2496 if ((file->f_mode & FMODE_WRITE) &&
2496 (file->f_flags & O_TRUNC)) { 2497 (file->f_flags & O_TRUNC)) {
2498 ftrace_graph_filter_enabled = 0;
2497 ftrace_graph_count = 0; 2499 ftrace_graph_count = 0;
2498 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs)); 2500 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
2499 } 2501 }
@@ -2519,7 +2521,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2519 struct dyn_ftrace *rec; 2521 struct dyn_ftrace *rec;
2520 struct ftrace_page *pg; 2522 struct ftrace_page *pg;
2521 int search_len; 2523 int search_len;
2522 int found = 0; 2524 int fail = 1;
2523 int type, not; 2525 int type, not;
2524 char *search; 2526 char *search;
2525 bool exists; 2527 bool exists;
@@ -2530,37 +2532,51 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2530 2532
2531 /* decode regex */ 2533 /* decode regex */
2532 type = filter_parse_regex(buffer, strlen(buffer), &search, &not); 2534 type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
2533 if (not) 2535 if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS)
2534 return -EINVAL; 2536 return -EBUSY;
2535 2537
2536 search_len = strlen(search); 2538 search_len = strlen(search);
2537 2539
2538 mutex_lock(&ftrace_lock); 2540 mutex_lock(&ftrace_lock);
2539 do_for_each_ftrace_rec(pg, rec) { 2541 do_for_each_ftrace_rec(pg, rec) {
2540 2542
2541 if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
2542 break;
2543
2544 if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE)) 2543 if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE))
2545 continue; 2544 continue;
2546 2545
2547 if (ftrace_match_record(rec, search, search_len, type)) { 2546 if (ftrace_match_record(rec, search, search_len, type)) {
2548 /* ensure it is not already in the array */ 2547 /* if it is in the array */
2549 exists = false; 2548 exists = false;
2550 for (i = 0; i < *idx; i++) 2549 for (i = 0; i < *idx; i++) {
2551 if (array[i] == rec->ip) { 2550 if (array[i] == rec->ip) {
2552 exists = true; 2551 exists = true;
2553 break; 2552 break;
2554 } 2553 }
2555 if (!exists) 2554 }
2556 array[(*idx)++] = rec->ip; 2555
2557 found = 1; 2556 if (!not) {
2557 fail = 0;
2558 if (!exists) {
2559 array[(*idx)++] = rec->ip;
2560 if (*idx >= FTRACE_GRAPH_MAX_FUNCS)
2561 goto out;
2562 }
2563 } else {
2564 if (exists) {
2565 array[i] = array[--(*idx)];
2566 array[*idx] = 0;
2567 fail = 0;
2568 }
2569 }
2558 } 2570 }
2559 } while_for_each_ftrace_rec(); 2571 } while_for_each_ftrace_rec();
2560 2572out:
2561 mutex_unlock(&ftrace_lock); 2573 mutex_unlock(&ftrace_lock);
2562 2574
2563 return found ? 0 : -EINVAL; 2575 if (fail)
2576 return -EINVAL;
2577
2578 ftrace_graph_filter_enabled = 1;
2579 return 0;
2564} 2580}
2565 2581
2566static ssize_t 2582static ssize_t
@@ -2570,16 +2586,11 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
2570 struct trace_parser parser; 2586 struct trace_parser parser;
2571 ssize_t read, ret; 2587 ssize_t read, ret;
2572 2588
2573 if (!cnt || cnt < 0) 2589 if (!cnt)
2574 return 0; 2590 return 0;
2575 2591
2576 mutex_lock(&graph_lock); 2592 mutex_lock(&graph_lock);
2577 2593
2578 if (ftrace_graph_count >= FTRACE_GRAPH_MAX_FUNCS) {
2579 ret = -EBUSY;
2580 goto out_unlock;
2581 }
2582
2583 if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) { 2594 if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
2584 ret = -ENOMEM; 2595 ret = -ENOMEM;
2585 goto out_unlock; 2596 goto out_unlock;