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.c144
1 files changed, 96 insertions, 48 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 0d88ce9b9fb8..f3dadae83883 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -381,12 +381,19 @@ static int function_stat_show(struct seq_file *m, void *v)
381{ 381{
382 struct ftrace_profile *rec = v; 382 struct ftrace_profile *rec = v;
383 char str[KSYM_SYMBOL_LEN]; 383 char str[KSYM_SYMBOL_LEN];
384 int ret = 0;
384#ifdef CONFIG_FUNCTION_GRAPH_TRACER 385#ifdef CONFIG_FUNCTION_GRAPH_TRACER
385 static DEFINE_MUTEX(mutex);
386 static struct trace_seq s; 386 static struct trace_seq s;
387 unsigned long long avg; 387 unsigned long long avg;
388 unsigned long long stddev; 388 unsigned long long stddev;
389#endif 389#endif
390 mutex_lock(&ftrace_profile_lock);
391
392 /* we raced with function_profile_reset() */
393 if (unlikely(rec->counter == 0)) {
394 ret = -EBUSY;
395 goto out;
396 }
390 397
391 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); 398 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
392 seq_printf(m, " %-30.30s %10lu", str, rec->counter); 399 seq_printf(m, " %-30.30s %10lu", str, rec->counter);
@@ -408,7 +415,6 @@ static int function_stat_show(struct seq_file *m, void *v)
408 do_div(stddev, (rec->counter - 1) * 1000); 415 do_div(stddev, (rec->counter - 1) * 1000);
409 } 416 }
410 417
411 mutex_lock(&mutex);
412 trace_seq_init(&s); 418 trace_seq_init(&s);
413 trace_print_graph_duration(rec->time, &s); 419 trace_print_graph_duration(rec->time, &s);
414 trace_seq_puts(&s, " "); 420 trace_seq_puts(&s, " ");
@@ -416,11 +422,12 @@ static int function_stat_show(struct seq_file *m, void *v)
416 trace_seq_puts(&s, " "); 422 trace_seq_puts(&s, " ");
417 trace_print_graph_duration(stddev, &s); 423 trace_print_graph_duration(stddev, &s);
418 trace_print_seq(m, &s); 424 trace_print_seq(m, &s);
419 mutex_unlock(&mutex);
420#endif 425#endif
421 seq_putc(m, '\n'); 426 seq_putc(m, '\n');
427out:
428 mutex_unlock(&ftrace_profile_lock);
422 429
423 return 0; 430 return ret;
424} 431}
425 432
426static void ftrace_profile_reset(struct ftrace_profile_stat *stat) 433static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
@@ -793,6 +800,7 @@ static const struct file_operations ftrace_profile_fops = {
793 .open = tracing_open_generic, 800 .open = tracing_open_generic,
794 .read = ftrace_profile_read, 801 .read = ftrace_profile_read,
795 .write = ftrace_profile_write, 802 .write = ftrace_profile_write,
803 .llseek = default_llseek,
796}; 804};
797 805
798/* used to initialize the real stat files */ 806/* used to initialize the real stat files */
@@ -877,10 +885,8 @@ enum {
877 FTRACE_ENABLE_CALLS = (1 << 0), 885 FTRACE_ENABLE_CALLS = (1 << 0),
878 FTRACE_DISABLE_CALLS = (1 << 1), 886 FTRACE_DISABLE_CALLS = (1 << 1),
879 FTRACE_UPDATE_TRACE_FUNC = (1 << 2), 887 FTRACE_UPDATE_TRACE_FUNC = (1 << 2),
880 FTRACE_ENABLE_MCOUNT = (1 << 3), 888 FTRACE_START_FUNC_RET = (1 << 3),
881 FTRACE_DISABLE_MCOUNT = (1 << 4), 889 FTRACE_STOP_FUNC_RET = (1 << 4),
882 FTRACE_START_FUNC_RET = (1 << 5),
883 FTRACE_STOP_FUNC_RET = (1 << 6),
884}; 890};
885 891
886static int ftrace_filtered; 892static int ftrace_filtered;
@@ -1219,8 +1225,6 @@ static void ftrace_shutdown(int command)
1219 1225
1220static void ftrace_startup_sysctl(void) 1226static void ftrace_startup_sysctl(void)
1221{ 1227{
1222 int command = FTRACE_ENABLE_MCOUNT;
1223
1224 if (unlikely(ftrace_disabled)) 1228 if (unlikely(ftrace_disabled))
1225 return; 1229 return;
1226 1230
@@ -1228,23 +1232,17 @@ static void ftrace_startup_sysctl(void)
1228 saved_ftrace_func = NULL; 1232 saved_ftrace_func = NULL;
1229 /* ftrace_start_up is true if we want ftrace running */ 1233 /* ftrace_start_up is true if we want ftrace running */
1230 if (ftrace_start_up) 1234 if (ftrace_start_up)
1231 command |= FTRACE_ENABLE_CALLS; 1235 ftrace_run_update_code(FTRACE_ENABLE_CALLS);
1232
1233 ftrace_run_update_code(command);
1234} 1236}
1235 1237
1236static void ftrace_shutdown_sysctl(void) 1238static void ftrace_shutdown_sysctl(void)
1237{ 1239{
1238 int command = FTRACE_DISABLE_MCOUNT;
1239
1240 if (unlikely(ftrace_disabled)) 1240 if (unlikely(ftrace_disabled))
1241 return; 1241 return;
1242 1242
1243 /* ftrace_start_up is true if ftrace is running */ 1243 /* ftrace_start_up is true if ftrace is running */
1244 if (ftrace_start_up) 1244 if (ftrace_start_up)
1245 command |= FTRACE_DISABLE_CALLS; 1245 ftrace_run_update_code(FTRACE_DISABLE_CALLS);
1246
1247 ftrace_run_update_code(command);
1248} 1246}
1249 1247
1250static cycle_t ftrace_update_time; 1248static cycle_t ftrace_update_time;
@@ -1361,24 +1359,29 @@ enum {
1361#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ 1359#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
1362 1360
1363struct ftrace_iterator { 1361struct ftrace_iterator {
1364 struct ftrace_page *pg; 1362 loff_t pos;
1365 int hidx; 1363 loff_t func_pos;
1366 int idx; 1364 struct ftrace_page *pg;
1367 unsigned flags; 1365 struct dyn_ftrace *func;
1368 struct trace_parser parser; 1366 struct ftrace_func_probe *probe;
1367 struct trace_parser parser;
1368 int hidx;
1369 int idx;
1370 unsigned flags;
1369}; 1371};
1370 1372
1371static void * 1373static void *
1372t_hash_next(struct seq_file *m, void *v, loff_t *pos) 1374t_hash_next(struct seq_file *m, loff_t *pos)
1373{ 1375{
1374 struct ftrace_iterator *iter = m->private; 1376 struct ftrace_iterator *iter = m->private;
1375 struct hlist_node *hnd = v; 1377 struct hlist_node *hnd = NULL;
1376 struct hlist_head *hhd; 1378 struct hlist_head *hhd;
1377 1379
1378 WARN_ON(!(iter->flags & FTRACE_ITER_HASH));
1379
1380 (*pos)++; 1380 (*pos)++;
1381 iter->pos = *pos;
1381 1382
1383 if (iter->probe)
1384 hnd = &iter->probe->node;
1382 retry: 1385 retry:
1383 if (iter->hidx >= FTRACE_FUNC_HASHSIZE) 1386 if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
1384 return NULL; 1387 return NULL;
@@ -1401,7 +1404,12 @@ t_hash_next(struct seq_file *m, void *v, loff_t *pos)
1401 } 1404 }
1402 } 1405 }
1403 1406
1404 return hnd; 1407 if (WARN_ON_ONCE(!hnd))
1408 return NULL;
1409
1410 iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node);
1411
1412 return iter;
1405} 1413}
1406 1414
1407static void *t_hash_start(struct seq_file *m, loff_t *pos) 1415static void *t_hash_start(struct seq_file *m, loff_t *pos)
@@ -1410,26 +1418,32 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos)
1410 void *p = NULL; 1418 void *p = NULL;
1411 loff_t l; 1419 loff_t l;
1412 1420
1413 if (!(iter->flags & FTRACE_ITER_HASH)) 1421 if (iter->func_pos > *pos)
1414 *pos = 0; 1422 return NULL;
1415
1416 iter->flags |= FTRACE_ITER_HASH;
1417 1423
1418 iter->hidx = 0; 1424 iter->hidx = 0;
1419 for (l = 0; l <= *pos; ) { 1425 for (l = 0; l <= (*pos - iter->func_pos); ) {
1420 p = t_hash_next(m, p, &l); 1426 p = t_hash_next(m, &l);
1421 if (!p) 1427 if (!p)
1422 break; 1428 break;
1423 } 1429 }
1424 return p; 1430 if (!p)
1431 return NULL;
1432
1433 /* Only set this if we have an item */
1434 iter->flags |= FTRACE_ITER_HASH;
1435
1436 return iter;
1425} 1437}
1426 1438
1427static int t_hash_show(struct seq_file *m, void *v) 1439static int
1440t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
1428{ 1441{
1429 struct ftrace_func_probe *rec; 1442 struct ftrace_func_probe *rec;
1430 struct hlist_node *hnd = v;
1431 1443
1432 rec = hlist_entry(hnd, struct ftrace_func_probe, node); 1444 rec = iter->probe;
1445 if (WARN_ON_ONCE(!rec))
1446 return -EIO;
1433 1447
1434 if (rec->ops->print) 1448 if (rec->ops->print)
1435 return rec->ops->print(m, rec->ip, rec->ops, rec->data); 1449 return rec->ops->print(m, rec->ip, rec->ops, rec->data);
@@ -1450,12 +1464,13 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
1450 struct dyn_ftrace *rec = NULL; 1464 struct dyn_ftrace *rec = NULL;
1451 1465
1452 if (iter->flags & FTRACE_ITER_HASH) 1466 if (iter->flags & FTRACE_ITER_HASH)
1453 return t_hash_next(m, v, pos); 1467 return t_hash_next(m, pos);
1454 1468
1455 (*pos)++; 1469 (*pos)++;
1470 iter->pos = *pos;
1456 1471
1457 if (iter->flags & FTRACE_ITER_PRINTALL) 1472 if (iter->flags & FTRACE_ITER_PRINTALL)
1458 return NULL; 1473 return t_hash_start(m, pos);
1459 1474
1460 retry: 1475 retry:
1461 if (iter->idx >= iter->pg->index) { 1476 if (iter->idx >= iter->pg->index) {
@@ -1484,7 +1499,20 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
1484 } 1499 }
1485 } 1500 }
1486 1501
1487 return rec; 1502 if (!rec)
1503 return t_hash_start(m, pos);
1504
1505 iter->func_pos = *pos;
1506 iter->func = rec;
1507
1508 return iter;
1509}
1510
1511static void reset_iter_read(struct ftrace_iterator *iter)
1512{
1513 iter->pos = 0;
1514 iter->func_pos = 0;
1515 iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH);
1488} 1516}
1489 1517
1490static void *t_start(struct seq_file *m, loff_t *pos) 1518static void *t_start(struct seq_file *m, loff_t *pos)
@@ -1495,6 +1523,12 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1495 1523
1496 mutex_lock(&ftrace_lock); 1524 mutex_lock(&ftrace_lock);
1497 /* 1525 /*
1526 * If an lseek was done, then reset and start from beginning.
1527 */
1528 if (*pos < iter->pos)
1529 reset_iter_read(iter);
1530
1531 /*
1498 * For set_ftrace_filter reading, if we have the filter 1532 * For set_ftrace_filter reading, if we have the filter
1499 * off, we can short cut and just print out that all 1533 * off, we can short cut and just print out that all
1500 * functions are enabled. 1534 * functions are enabled.
@@ -1503,12 +1537,19 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1503 if (*pos > 0) 1537 if (*pos > 0)
1504 return t_hash_start(m, pos); 1538 return t_hash_start(m, pos);
1505 iter->flags |= FTRACE_ITER_PRINTALL; 1539 iter->flags |= FTRACE_ITER_PRINTALL;
1540 /* reset in case of seek/pread */
1541 iter->flags &= ~FTRACE_ITER_HASH;
1506 return iter; 1542 return iter;
1507 } 1543 }
1508 1544
1509 if (iter->flags & FTRACE_ITER_HASH) 1545 if (iter->flags & FTRACE_ITER_HASH)
1510 return t_hash_start(m, pos); 1546 return t_hash_start(m, pos);
1511 1547
1548 /*
1549 * Unfortunately, we need to restart at ftrace_pages_start
1550 * every time we let go of the ftrace_mutex. This is because
1551 * those pointers can change without the lock.
1552 */
1512 iter->pg = ftrace_pages_start; 1553 iter->pg = ftrace_pages_start;
1513 iter->idx = 0; 1554 iter->idx = 0;
1514 for (l = 0; l <= *pos; ) { 1555 for (l = 0; l <= *pos; ) {
@@ -1517,10 +1558,14 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1517 break; 1558 break;
1518 } 1559 }
1519 1560
1520 if (!p && iter->flags & FTRACE_ITER_FILTER) 1561 if (!p) {
1521 return t_hash_start(m, pos); 1562 if (iter->flags & FTRACE_ITER_FILTER)
1563 return t_hash_start(m, pos);
1522 1564
1523 return p; 1565 return NULL;
1566 }
1567
1568 return iter;
1524} 1569}
1525 1570
1526static void t_stop(struct seq_file *m, void *p) 1571static void t_stop(struct seq_file *m, void *p)
@@ -1531,16 +1576,18 @@ static void t_stop(struct seq_file *m, void *p)
1531static int t_show(struct seq_file *m, void *v) 1576static int t_show(struct seq_file *m, void *v)
1532{ 1577{
1533 struct ftrace_iterator *iter = m->private; 1578 struct ftrace_iterator *iter = m->private;
1534 struct dyn_ftrace *rec = v; 1579 struct dyn_ftrace *rec;
1535 1580
1536 if (iter->flags & FTRACE_ITER_HASH) 1581 if (iter->flags & FTRACE_ITER_HASH)
1537 return t_hash_show(m, v); 1582 return t_hash_show(m, iter);
1538 1583
1539 if (iter->flags & FTRACE_ITER_PRINTALL) { 1584 if (iter->flags & FTRACE_ITER_PRINTALL) {
1540 seq_printf(m, "#### all functions enabled ####\n"); 1585 seq_printf(m, "#### all functions enabled ####\n");
1541 return 0; 1586 return 0;
1542 } 1587 }
1543 1588
1589 rec = iter->func;
1590
1544 if (!rec) 1591 if (!rec)
1545 return 0; 1592 return 0;
1546 1593
@@ -1592,8 +1639,8 @@ ftrace_failures_open(struct inode *inode, struct file *file)
1592 1639
1593 ret = ftrace_avail_open(inode, file); 1640 ret = ftrace_avail_open(inode, file);
1594 if (!ret) { 1641 if (!ret) {
1595 m = (struct seq_file *)file->private_data; 1642 m = file->private_data;
1596 iter = (struct ftrace_iterator *)m->private; 1643 iter = m->private;
1597 iter->flags = FTRACE_ITER_FAILURES; 1644 iter->flags = FTRACE_ITER_FAILURES;
1598 } 1645 }
1599 1646
@@ -2623,6 +2670,7 @@ static const struct file_operations ftrace_graph_fops = {
2623 .read = seq_read, 2670 .read = seq_read,
2624 .write = ftrace_graph_write, 2671 .write = ftrace_graph_write,
2625 .release = ftrace_graph_release, 2672 .release = ftrace_graph_release,
2673 .llseek = seq_lseek,
2626}; 2674};
2627#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 2675#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2628 2676