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.c129
1 files changed, 84 insertions, 45 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index fa7ece649fe1..f3dadae83883 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -800,6 +800,7 @@ static const struct file_operations ftrace_profile_fops = {
800 .open = tracing_open_generic, 800 .open = tracing_open_generic,
801 .read = ftrace_profile_read, 801 .read = ftrace_profile_read,
802 .write = ftrace_profile_write, 802 .write = ftrace_profile_write,
803 .llseek = default_llseek,
803}; 804};
804 805
805/* used to initialize the real stat files */ 806/* used to initialize the real stat files */
@@ -884,10 +885,8 @@ enum {
884 FTRACE_ENABLE_CALLS = (1 << 0), 885 FTRACE_ENABLE_CALLS = (1 << 0),
885 FTRACE_DISABLE_CALLS = (1 << 1), 886 FTRACE_DISABLE_CALLS = (1 << 1),
886 FTRACE_UPDATE_TRACE_FUNC = (1 << 2), 887 FTRACE_UPDATE_TRACE_FUNC = (1 << 2),
887 FTRACE_ENABLE_MCOUNT = (1 << 3), 888 FTRACE_START_FUNC_RET = (1 << 3),
888 FTRACE_DISABLE_MCOUNT = (1 << 4), 889 FTRACE_STOP_FUNC_RET = (1 << 4),
889 FTRACE_START_FUNC_RET = (1 << 5),
890 FTRACE_STOP_FUNC_RET = (1 << 6),
891}; 890};
892 891
893static int ftrace_filtered; 892static int ftrace_filtered;
@@ -1226,8 +1225,6 @@ static void ftrace_shutdown(int command)
1226 1225
1227static void ftrace_startup_sysctl(void) 1226static void ftrace_startup_sysctl(void)
1228{ 1227{
1229 int command = FTRACE_ENABLE_MCOUNT;
1230
1231 if (unlikely(ftrace_disabled)) 1228 if (unlikely(ftrace_disabled))
1232 return; 1229 return;
1233 1230
@@ -1235,23 +1232,17 @@ static void ftrace_startup_sysctl(void)
1235 saved_ftrace_func = NULL; 1232 saved_ftrace_func = NULL;
1236 /* ftrace_start_up is true if we want ftrace running */ 1233 /* ftrace_start_up is true if we want ftrace running */
1237 if (ftrace_start_up) 1234 if (ftrace_start_up)
1238 command |= FTRACE_ENABLE_CALLS; 1235 ftrace_run_update_code(FTRACE_ENABLE_CALLS);
1239
1240 ftrace_run_update_code(command);
1241} 1236}
1242 1237
1243static void ftrace_shutdown_sysctl(void) 1238static void ftrace_shutdown_sysctl(void)
1244{ 1239{
1245 int command = FTRACE_DISABLE_MCOUNT;
1246
1247 if (unlikely(ftrace_disabled)) 1240 if (unlikely(ftrace_disabled))
1248 return; 1241 return;
1249 1242
1250 /* ftrace_start_up is true if ftrace is running */ 1243 /* ftrace_start_up is true if ftrace is running */
1251 if (ftrace_start_up) 1244 if (ftrace_start_up)
1252 command |= FTRACE_DISABLE_CALLS; 1245 ftrace_run_update_code(FTRACE_DISABLE_CALLS);
1253
1254 ftrace_run_update_code(command);
1255} 1246}
1256 1247
1257static cycle_t ftrace_update_time; 1248static cycle_t ftrace_update_time;
@@ -1368,24 +1359,29 @@ enum {
1368#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ 1359#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
1369 1360
1370struct ftrace_iterator { 1361struct ftrace_iterator {
1371 struct ftrace_page *pg; 1362 loff_t pos;
1372 int hidx; 1363 loff_t func_pos;
1373 int idx; 1364 struct ftrace_page *pg;
1374 unsigned flags; 1365 struct dyn_ftrace *func;
1375 struct trace_parser parser; 1366 struct ftrace_func_probe *probe;
1367 struct trace_parser parser;
1368 int hidx;
1369 int idx;
1370 unsigned flags;
1376}; 1371};
1377 1372
1378static void * 1373static void *
1379t_hash_next(struct seq_file *m, void *v, loff_t *pos) 1374t_hash_next(struct seq_file *m, loff_t *pos)
1380{ 1375{
1381 struct ftrace_iterator *iter = m->private; 1376 struct ftrace_iterator *iter = m->private;
1382 struct hlist_node *hnd = v; 1377 struct hlist_node *hnd = NULL;
1383 struct hlist_head *hhd; 1378 struct hlist_head *hhd;
1384 1379
1385 WARN_ON(!(iter->flags & FTRACE_ITER_HASH));
1386
1387 (*pos)++; 1380 (*pos)++;
1381 iter->pos = *pos;
1388 1382
1383 if (iter->probe)
1384 hnd = &iter->probe->node;
1389 retry: 1385 retry:
1390 if (iter->hidx >= FTRACE_FUNC_HASHSIZE) 1386 if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
1391 return NULL; 1387 return NULL;
@@ -1408,7 +1404,12 @@ t_hash_next(struct seq_file *m, void *v, loff_t *pos)
1408 } 1404 }
1409 } 1405 }
1410 1406
1411 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;
1412} 1413}
1413 1414
1414static void *t_hash_start(struct seq_file *m, loff_t *pos) 1415static void *t_hash_start(struct seq_file *m, loff_t *pos)
@@ -1417,26 +1418,32 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos)
1417 void *p = NULL; 1418 void *p = NULL;
1418 loff_t l; 1419 loff_t l;
1419 1420
1420 if (!(iter->flags & FTRACE_ITER_HASH)) 1421 if (iter->func_pos > *pos)
1421 *pos = 0; 1422 return NULL;
1422
1423 iter->flags |= FTRACE_ITER_HASH;
1424 1423
1425 iter->hidx = 0; 1424 iter->hidx = 0;
1426 for (l = 0; l <= *pos; ) { 1425 for (l = 0; l <= (*pos - iter->func_pos); ) {
1427 p = t_hash_next(m, p, &l); 1426 p = t_hash_next(m, &l);
1428 if (!p) 1427 if (!p)
1429 break; 1428 break;
1430 } 1429 }
1431 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;
1432} 1437}
1433 1438
1434static int t_hash_show(struct seq_file *m, void *v) 1439static int
1440t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
1435{ 1441{
1436 struct ftrace_func_probe *rec; 1442 struct ftrace_func_probe *rec;
1437 struct hlist_node *hnd = v;
1438 1443
1439 rec = hlist_entry(hnd, struct ftrace_func_probe, node); 1444 rec = iter->probe;
1445 if (WARN_ON_ONCE(!rec))
1446 return -EIO;
1440 1447
1441 if (rec->ops->print) 1448 if (rec->ops->print)
1442 return rec->ops->print(m, rec->ip, rec->ops, rec->data); 1449 return rec->ops->print(m, rec->ip, rec->ops, rec->data);
@@ -1457,12 +1464,13 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
1457 struct dyn_ftrace *rec = NULL; 1464 struct dyn_ftrace *rec = NULL;
1458 1465
1459 if (iter->flags & FTRACE_ITER_HASH) 1466 if (iter->flags & FTRACE_ITER_HASH)
1460 return t_hash_next(m, v, pos); 1467 return t_hash_next(m, pos);
1461 1468
1462 (*pos)++; 1469 (*pos)++;
1470 iter->pos = *pos;
1463 1471
1464 if (iter->flags & FTRACE_ITER_PRINTALL) 1472 if (iter->flags & FTRACE_ITER_PRINTALL)
1465 return NULL; 1473 return t_hash_start(m, pos);
1466 1474
1467 retry: 1475 retry:
1468 if (iter->idx >= iter->pg->index) { 1476 if (iter->idx >= iter->pg->index) {
@@ -1491,7 +1499,20 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
1491 } 1499 }
1492 } 1500 }
1493 1501
1494 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);
1495} 1516}
1496 1517
1497static void *t_start(struct seq_file *m, loff_t *pos) 1518static void *t_start(struct seq_file *m, loff_t *pos)
@@ -1502,6 +1523,12 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1502 1523
1503 mutex_lock(&ftrace_lock); 1524 mutex_lock(&ftrace_lock);
1504 /* 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 /*
1505 * For set_ftrace_filter reading, if we have the filter 1532 * For set_ftrace_filter reading, if we have the filter
1506 * off, we can short cut and just print out that all 1533 * off, we can short cut and just print out that all
1507 * functions are enabled. 1534 * functions are enabled.
@@ -1518,6 +1545,11 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1518 if (iter->flags & FTRACE_ITER_HASH) 1545 if (iter->flags & FTRACE_ITER_HASH)
1519 return t_hash_start(m, pos); 1546 return t_hash_start(m, pos);
1520 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 */
1521 iter->pg = ftrace_pages_start; 1553 iter->pg = ftrace_pages_start;
1522 iter->idx = 0; 1554 iter->idx = 0;
1523 for (l = 0; l <= *pos; ) { 1555 for (l = 0; l <= *pos; ) {
@@ -1526,10 +1558,14 @@ static void *t_start(struct seq_file *m, loff_t *pos)
1526 break; 1558 break;
1527 } 1559 }
1528 1560
1529 if (!p && iter->flags & FTRACE_ITER_FILTER) 1561 if (!p) {
1530 return t_hash_start(m, pos); 1562 if (iter->flags & FTRACE_ITER_FILTER)
1563 return t_hash_start(m, pos);
1564
1565 return NULL;
1566 }
1531 1567
1532 return p; 1568 return iter;
1533} 1569}
1534 1570
1535static void t_stop(struct seq_file *m, void *p) 1571static void t_stop(struct seq_file *m, void *p)
@@ -1540,16 +1576,18 @@ static void t_stop(struct seq_file *m, void *p)
1540static int t_show(struct seq_file *m, void *v) 1576static int t_show(struct seq_file *m, void *v)
1541{ 1577{
1542 struct ftrace_iterator *iter = m->private; 1578 struct ftrace_iterator *iter = m->private;
1543 struct dyn_ftrace *rec = v; 1579 struct dyn_ftrace *rec;
1544 1580
1545 if (iter->flags & FTRACE_ITER_HASH) 1581 if (iter->flags & FTRACE_ITER_HASH)
1546 return t_hash_show(m, v); 1582 return t_hash_show(m, iter);
1547 1583
1548 if (iter->flags & FTRACE_ITER_PRINTALL) { 1584 if (iter->flags & FTRACE_ITER_PRINTALL) {
1549 seq_printf(m, "#### all functions enabled ####\n"); 1585 seq_printf(m, "#### all functions enabled ####\n");
1550 return 0; 1586 return 0;
1551 } 1587 }
1552 1588
1589 rec = iter->func;
1590
1553 if (!rec) 1591 if (!rec)
1554 return 0; 1592 return 0;
1555 1593
@@ -1601,8 +1639,8 @@ ftrace_failures_open(struct inode *inode, struct file *file)
1601 1639
1602 ret = ftrace_avail_open(inode, file); 1640 ret = ftrace_avail_open(inode, file);
1603 if (!ret) { 1641 if (!ret) {
1604 m = (struct seq_file *)file->private_data; 1642 m = file->private_data;
1605 iter = (struct ftrace_iterator *)m->private; 1643 iter = m->private;
1606 iter->flags = FTRACE_ITER_FAILURES; 1644 iter->flags = FTRACE_ITER_FAILURES;
1607 } 1645 }
1608 1646
@@ -2418,7 +2456,7 @@ static const struct file_operations ftrace_filter_fops = {
2418 .open = ftrace_filter_open, 2456 .open = ftrace_filter_open,
2419 .read = seq_read, 2457 .read = seq_read,
2420 .write = ftrace_filter_write, 2458 .write = ftrace_filter_write,
2421 .llseek = no_llseek, 2459 .llseek = ftrace_regex_lseek,
2422 .release = ftrace_filter_release, 2460 .release = ftrace_filter_release,
2423}; 2461};
2424 2462
@@ -2632,6 +2670,7 @@ static const struct file_operations ftrace_graph_fops = {
2632 .read = seq_read, 2670 .read = seq_read,
2633 .write = ftrace_graph_write, 2671 .write = ftrace_graph_write,
2634 .release = ftrace_graph_release, 2672 .release = ftrace_graph_release,
2673 .llseek = seq_lseek,
2635}; 2674};
2636#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 2675#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2637 2676