aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/ftrace.c345
-rw-r--r--kernel/trace/trace.c11
-rw-r--r--kernel/trace/trace.h44
3 files changed, 386 insertions, 14 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 65b9e863056b..d2b156538162 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -47,8 +47,9 @@
47int ftrace_enabled __read_mostly; 47int ftrace_enabled __read_mostly;
48static int last_ftrace_enabled; 48static int last_ftrace_enabled;
49 49
50/* ftrace_pid_trace >= 0 will only trace threads with this pid */ 50/* set when tracing only a pid */
51static int ftrace_pid_trace = -1; 51struct pid *ftrace_pid_trace;
52static struct pid * const ftrace_swapper_pid = (struct pid *)1;
52 53
53/* Quick disabling of function tracer. */ 54/* Quick disabling of function tracer. */
54int function_trace_stop; 55int function_trace_stop;
@@ -90,7 +91,7 @@ static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
90 91
91static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip) 92static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip)
92{ 93{
93 if (current->pid != ftrace_pid_trace) 94 if (!test_tsk_trace_trace(current))
94 return; 95 return;
95 96
96 ftrace_pid_function(ip, parent_ip); 97 ftrace_pid_function(ip, parent_ip);
@@ -153,7 +154,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
153 else 154 else
154 func = ftrace_list_func; 155 func = ftrace_list_func;
155 156
156 if (ftrace_pid_trace >= 0) { 157 if (ftrace_pid_trace) {
157 set_ftrace_pid_function(func); 158 set_ftrace_pid_function(func);
158 func = ftrace_pid_func; 159 func = ftrace_pid_func;
159 } 160 }
@@ -209,7 +210,7 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
209 if (ftrace_list->next == &ftrace_list_end) { 210 if (ftrace_list->next == &ftrace_list_end) {
210 ftrace_func_t func = ftrace_list->func; 211 ftrace_func_t func = ftrace_list->func;
211 212
212 if (ftrace_pid_trace >= 0) { 213 if (ftrace_pid_trace) {
213 set_ftrace_pid_function(func); 214 set_ftrace_pid_function(func);
214 func = ftrace_pid_func; 215 func = ftrace_pid_func;
215 } 216 }
@@ -239,7 +240,7 @@ static void ftrace_update_pid_func(void)
239 240
240 func = ftrace_trace_function; 241 func = ftrace_trace_function;
241 242
242 if (ftrace_pid_trace >= 0) { 243 if (ftrace_pid_trace) {
243 set_ftrace_pid_function(func); 244 set_ftrace_pid_function(func);
244 func = ftrace_pid_func; 245 func = ftrace_pid_func;
245 } else { 246 } else {
@@ -1320,6 +1321,230 @@ static struct file_operations ftrace_notrace_fops = {
1320 .release = ftrace_notrace_release, 1321 .release = ftrace_notrace_release,
1321}; 1322};
1322 1323
1324#ifdef CONFIG_FUNCTION_GRAPH_TRACER
1325
1326static DEFINE_MUTEX(graph_lock);
1327
1328int ftrace_graph_count;
1329unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
1330
1331static void *
1332g_next(struct seq_file *m, void *v, loff_t *pos)
1333{
1334 unsigned long *array = m->private;
1335 int index = *pos;
1336
1337 (*pos)++;
1338
1339 if (index >= ftrace_graph_count)
1340 return NULL;
1341
1342 return &array[index];
1343}
1344
1345static void *g_start(struct seq_file *m, loff_t *pos)
1346{
1347 void *p = NULL;
1348
1349 mutex_lock(&graph_lock);
1350
1351 p = g_next(m, p, pos);
1352
1353 return p;
1354}
1355
1356static void g_stop(struct seq_file *m, void *p)
1357{
1358 mutex_unlock(&graph_lock);
1359}
1360
1361static int g_show(struct seq_file *m, void *v)
1362{
1363 unsigned long *ptr = v;
1364 char str[KSYM_SYMBOL_LEN];
1365
1366 if (!ptr)
1367 return 0;
1368
1369 kallsyms_lookup(*ptr, NULL, NULL, NULL, str);
1370
1371 seq_printf(m, "%s\n", str);
1372
1373 return 0;
1374}
1375
1376static struct seq_operations ftrace_graph_seq_ops = {
1377 .start = g_start,
1378 .next = g_next,
1379 .stop = g_stop,
1380 .show = g_show,
1381};
1382
1383static int
1384ftrace_graph_open(struct inode *inode, struct file *file)
1385{
1386 int ret = 0;
1387
1388 if (unlikely(ftrace_disabled))
1389 return -ENODEV;
1390
1391 mutex_lock(&graph_lock);
1392 if ((file->f_mode & FMODE_WRITE) &&
1393 !(file->f_flags & O_APPEND)) {
1394 ftrace_graph_count = 0;
1395 memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
1396 }
1397
1398 if (file->f_mode & FMODE_READ) {
1399 ret = seq_open(file, &ftrace_graph_seq_ops);
1400 if (!ret) {
1401 struct seq_file *m = file->private_data;
1402 m->private = ftrace_graph_funcs;
1403 }
1404 } else
1405 file->private_data = ftrace_graph_funcs;
1406 mutex_unlock(&graph_lock);
1407
1408 return ret;
1409}
1410
1411static ssize_t
1412ftrace_graph_read(struct file *file, char __user *ubuf,
1413 size_t cnt, loff_t *ppos)
1414{
1415 if (file->f_mode & FMODE_READ)
1416 return seq_read(file, ubuf, cnt, ppos);
1417 else
1418 return -EPERM;
1419}
1420
1421static int
1422ftrace_set_func(unsigned long *array, int idx, char *buffer)
1423{
1424 char str[KSYM_SYMBOL_LEN];
1425 struct dyn_ftrace *rec;
1426 struct ftrace_page *pg;
1427 int found = 0;
1428 int i, j;
1429
1430 if (ftrace_disabled)
1431 return -ENODEV;
1432
1433 /* should not be called from interrupt context */
1434 spin_lock(&ftrace_lock);
1435
1436 for (pg = ftrace_pages_start; pg; pg = pg->next) {
1437 for (i = 0; i < pg->index; i++) {
1438 rec = &pg->records[i];
1439
1440 if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE))
1441 continue;
1442
1443 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
1444 if (strcmp(str, buffer) == 0) {
1445 found = 1;
1446 for (j = 0; j < idx; j++)
1447 if (array[j] == rec->ip) {
1448 found = 0;
1449 break;
1450 }
1451 if (found)
1452 array[idx] = rec->ip;
1453 break;
1454 }
1455 }
1456 }
1457 spin_unlock(&ftrace_lock);
1458
1459 return found ? 0 : -EINVAL;
1460}
1461
1462static ssize_t
1463ftrace_graph_write(struct file *file, const char __user *ubuf,
1464 size_t cnt, loff_t *ppos)
1465{
1466 unsigned char buffer[FTRACE_BUFF_MAX+1];
1467 unsigned long *array;
1468 size_t read = 0;
1469 ssize_t ret;
1470 int index = 0;
1471 char ch;
1472
1473 if (!cnt || cnt < 0)
1474 return 0;
1475
1476 mutex_lock(&graph_lock);
1477
1478 if (ftrace_graph_count >= FTRACE_GRAPH_MAX_FUNCS) {
1479 ret = -EBUSY;
1480 goto out;
1481 }
1482
1483 if (file->f_mode & FMODE_READ) {
1484 struct seq_file *m = file->private_data;
1485 array = m->private;
1486 } else
1487 array = file->private_data;
1488
1489 ret = get_user(ch, ubuf++);
1490 if (ret)
1491 goto out;
1492 read++;
1493 cnt--;
1494
1495 /* skip white space */
1496 while (cnt && isspace(ch)) {
1497 ret = get_user(ch, ubuf++);
1498 if (ret)
1499 goto out;
1500 read++;
1501 cnt--;
1502 }
1503
1504 if (isspace(ch)) {
1505 *ppos += read;
1506 ret = read;
1507 goto out;
1508 }
1509
1510 while (cnt && !isspace(ch)) {
1511 if (index < FTRACE_BUFF_MAX)
1512 buffer[index++] = ch;
1513 else {
1514 ret = -EINVAL;
1515 goto out;
1516 }
1517 ret = get_user(ch, ubuf++);
1518 if (ret)
1519 goto out;
1520 read++;
1521 cnt--;
1522 }
1523 buffer[index] = 0;
1524
1525 /* we allow only one at a time */
1526 ret = ftrace_set_func(array, ftrace_graph_count, buffer);
1527 if (ret)
1528 goto out;
1529
1530 ftrace_graph_count++;
1531
1532 file->f_pos += read;
1533
1534 ret = read;
1535 out:
1536 mutex_unlock(&graph_lock);
1537
1538 return ret;
1539}
1540
1541static const struct file_operations ftrace_graph_fops = {
1542 .open = ftrace_graph_open,
1543 .read = ftrace_graph_read,
1544 .write = ftrace_graph_write,
1545};
1546#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
1547
1323static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer) 1548static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
1324{ 1549{
1325 struct dentry *entry; 1550 struct dentry *entry;
@@ -1347,6 +1572,15 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
1347 pr_warning("Could not create debugfs " 1572 pr_warning("Could not create debugfs "
1348 "'set_ftrace_notrace' entry\n"); 1573 "'set_ftrace_notrace' entry\n");
1349 1574
1575#ifdef CONFIG_FUNCTION_GRAPH_TRACER
1576 entry = debugfs_create_file("set_graph_function", 0444, d_tracer,
1577 NULL,
1578 &ftrace_graph_fops);
1579 if (!entry)
1580 pr_warning("Could not create debugfs "
1581 "'set_graph_function' entry\n");
1582#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
1583
1350 return 0; 1584 return 0;
1351} 1585}
1352 1586
@@ -1451,18 +1685,84 @@ ftrace_pid_read(struct file *file, char __user *ubuf,
1451 char buf[64]; 1685 char buf[64];
1452 int r; 1686 int r;
1453 1687
1454 if (ftrace_pid_trace >= 0) 1688 if (ftrace_pid_trace == ftrace_swapper_pid)
1455 r = sprintf(buf, "%u\n", ftrace_pid_trace); 1689 r = sprintf(buf, "swapper tasks\n");
1690 else if (ftrace_pid_trace)
1691 r = sprintf(buf, "%u\n", pid_nr(ftrace_pid_trace));
1456 else 1692 else
1457 r = sprintf(buf, "no pid\n"); 1693 r = sprintf(buf, "no pid\n");
1458 1694
1459 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 1695 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1460} 1696}
1461 1697
1698static void clear_ftrace_swapper(void)
1699{
1700 struct task_struct *p;
1701 int cpu;
1702
1703 get_online_cpus();
1704 for_each_online_cpu(cpu) {
1705 p = idle_task(cpu);
1706 clear_tsk_trace_trace(p);
1707 }
1708 put_online_cpus();
1709}
1710
1711static void set_ftrace_swapper(void)
1712{
1713 struct task_struct *p;
1714 int cpu;
1715
1716 get_online_cpus();
1717 for_each_online_cpu(cpu) {
1718 p = idle_task(cpu);
1719 set_tsk_trace_trace(p);
1720 }
1721 put_online_cpus();
1722}
1723
1724static void clear_ftrace_pid(struct pid *pid)
1725{
1726 struct task_struct *p;
1727
1728 do_each_pid_task(pid, PIDTYPE_PID, p) {
1729 clear_tsk_trace_trace(p);
1730 } while_each_pid_task(pid, PIDTYPE_PID, p);
1731 put_pid(pid);
1732}
1733
1734static void set_ftrace_pid(struct pid *pid)
1735{
1736 struct task_struct *p;
1737
1738 do_each_pid_task(pid, PIDTYPE_PID, p) {
1739 set_tsk_trace_trace(p);
1740 } while_each_pid_task(pid, PIDTYPE_PID, p);
1741}
1742
1743static void clear_ftrace_pid_task(struct pid **pid)
1744{
1745 if (*pid == ftrace_swapper_pid)
1746 clear_ftrace_swapper();
1747 else
1748 clear_ftrace_pid(*pid);
1749
1750 *pid = NULL;
1751}
1752
1753static void set_ftrace_pid_task(struct pid *pid)
1754{
1755 if (pid == ftrace_swapper_pid)
1756 set_ftrace_swapper();
1757 else
1758 set_ftrace_pid(pid);
1759}
1760
1462static ssize_t 1761static ssize_t
1463ftrace_pid_write(struct file *filp, const char __user *ubuf, 1762ftrace_pid_write(struct file *filp, const char __user *ubuf,
1464 size_t cnt, loff_t *ppos) 1763 size_t cnt, loff_t *ppos)
1465{ 1764{
1765 struct pid *pid;
1466 char buf[64]; 1766 char buf[64];
1467 long val; 1767 long val;
1468 int ret; 1768 int ret;
@@ -1480,18 +1780,37 @@ ftrace_pid_write(struct file *filp, const char __user *ubuf,
1480 return ret; 1780 return ret;
1481 1781
1482 mutex_lock(&ftrace_start_lock); 1782 mutex_lock(&ftrace_start_lock);
1483 if (ret < 0) { 1783 if (val < 0) {
1484 /* disable pid tracing */ 1784 /* disable pid tracing */
1485 if (ftrace_pid_trace < 0) 1785 if (!ftrace_pid_trace)
1486 goto out; 1786 goto out;
1487 ftrace_pid_trace = -1; 1787
1788 clear_ftrace_pid_task(&ftrace_pid_trace);
1488 1789
1489 } else { 1790 } else {
1791 /* swapper task is special */
1792 if (!val) {
1793 pid = ftrace_swapper_pid;
1794 if (pid == ftrace_pid_trace)
1795 goto out;
1796 } else {
1797 pid = find_get_pid(val);
1490 1798
1491 if (ftrace_pid_trace == val) 1799 if (pid == ftrace_pid_trace) {
1800 put_pid(pid);
1801 goto out;
1802 }
1803 }
1804
1805 if (ftrace_pid_trace)
1806 clear_ftrace_pid_task(&ftrace_pid_trace);
1807
1808 if (!pid)
1492 goto out; 1809 goto out;
1493 1810
1494 ftrace_pid_trace = val; 1811 ftrace_pid_trace = pid;
1812
1813 set_ftrace_pid_task(ftrace_pid_trace);
1495 } 1814 }
1496 1815
1497 /* update the function call */ 1816 /* update the function call */
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 1ca74c0cee6a..ea38652d631c 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1209,6 +1209,12 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
1209 int cpu; 1209 int cpu;
1210 int pc; 1210 int pc;
1211 1211
1212 if (!ftrace_trace_task(current))
1213 return 0;
1214
1215 if (!ftrace_graph_addr(trace->func))
1216 return 0;
1217
1212 local_irq_save(flags); 1218 local_irq_save(flags);
1213 cpu = raw_smp_processor_id(); 1219 cpu = raw_smp_processor_id();
1214 data = tr->data[cpu]; 1220 data = tr->data[cpu];
@@ -1217,6 +1223,9 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
1217 pc = preempt_count(); 1223 pc = preempt_count();
1218 __trace_graph_entry(tr, data, trace, flags, pc); 1224 __trace_graph_entry(tr, data, trace, flags, pc);
1219 } 1225 }
1226 /* Only do the atomic if it is not already set */
1227 if (!test_tsk_trace_graph(current))
1228 set_tsk_trace_graph(current);
1220 atomic_dec(&data->disabled); 1229 atomic_dec(&data->disabled);
1221 local_irq_restore(flags); 1230 local_irq_restore(flags);
1222 1231
@@ -1240,6 +1249,8 @@ void trace_graph_return(struct ftrace_graph_ret *trace)
1240 pc = preempt_count(); 1249 pc = preempt_count();
1241 __trace_graph_return(tr, data, trace, flags, pc); 1250 __trace_graph_return(tr, data, trace, flags, pc);
1242 } 1251 }
1252 if (!trace->depth)
1253 clear_tsk_trace_graph(current);
1243 atomic_dec(&data->disabled); 1254 atomic_dec(&data->disabled);
1244 local_irq_restore(flags); 1255 local_irq_restore(flags);
1245} 1256}
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index fce98898205a..a71bbe0a3631 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -507,13 +507,55 @@ extern unsigned long trace_flags;
507/* Standard output formatting function used for function return traces */ 507/* Standard output formatting function used for function return traces */
508#ifdef CONFIG_FUNCTION_GRAPH_TRACER 508#ifdef CONFIG_FUNCTION_GRAPH_TRACER
509extern enum print_line_t print_graph_function(struct trace_iterator *iter); 509extern enum print_line_t print_graph_function(struct trace_iterator *iter);
510
511#ifdef CONFIG_DYNAMIC_FTRACE
512/* TODO: make this variable */
513#define FTRACE_GRAPH_MAX_FUNCS 32
514extern int ftrace_graph_count;
515extern unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS];
516
517static inline int ftrace_graph_addr(unsigned long addr)
518{
519 int i;
520
521 if (!ftrace_graph_count || test_tsk_trace_graph(current))
522 return 1;
523
524 for (i = 0; i < ftrace_graph_count; i++) {
525 if (addr == ftrace_graph_funcs[i])
526 return 1;
527 }
528
529 return 0;
530}
510#else 531#else
532static inline int ftrace_trace_addr(unsigned long addr)
533{
534 return 1;
535}
536static inline int ftrace_graph_addr(unsigned long addr)
537{
538 return 1;
539}
540#endif /* CONFIG_DYNAMIC_FTRACE */
541
542#else /* CONFIG_FUNCTION_GRAPH_TRACER */
511static inline enum print_line_t 543static inline enum print_line_t
512print_graph_function(struct trace_iterator *iter) 544print_graph_function(struct trace_iterator *iter)
513{ 545{
514 return TRACE_TYPE_UNHANDLED; 546 return TRACE_TYPE_UNHANDLED;
515} 547}
516#endif 548#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
549
550extern struct pid *ftrace_pid_trace;
551
552static inline int ftrace_trace_task(struct task_struct *task)
553{
554 if (ftrace_pid_trace)
555 return 1;
556
557 return test_tsk_trace_trace(task);
558}
517 559
518/* 560/*
519 * trace_iterator_flags is an enumeration that defines bit 561 * trace_iterator_flags is an enumeration that defines bit