trace.c (c47956d9ae3341d2d1998bff26620fa3338c01e4) trace.c (f0868d1e23a8efec33beb3aa688aab7fdb1ae093)
1/*
2 * ring buffer based function tracer
3 *
4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5 * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
6 *
7 * Originally taken from the RT patch by:
8 * Arnaldo Carvalho de Melo <acme@redhat.com>

--- 24 unchanged lines hidden (view full) ---

33#include <linux/seq_file.h>
34#include <linux/writeback.h>
35
36#include <linux/stacktrace.h>
37#include <linux/ring_buffer.h>
38#include <linux/irqflags.h>
39
40#include "trace.h"
1/*
2 * ring buffer based function tracer
3 *
4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5 * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
6 *
7 * Originally taken from the RT patch by:
8 * Arnaldo Carvalho de Melo <acme@redhat.com>

--- 24 unchanged lines hidden (view full) ---

33#include <linux/seq_file.h>
34#include <linux/writeback.h>
35
36#include <linux/stacktrace.h>
37#include <linux/ring_buffer.h>
38#include <linux/irqflags.h>
39
40#include "trace.h"
41#include "trace_output.h"
41
42#define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE)
43
44unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX;
45unsigned long __read_mostly tracing_thresh;
46
47/*
48 * We need to change this state when a selftest is running.

--- 276 unchanged lines hidden (view full) ---

325 data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
326 data->policy = tsk->policy;
327 data->rt_priority = tsk->rt_priority;
328
329 /* record this tasks comm */
330 tracing_record_cmdline(current);
331}
332
42
43#define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE)
44
45unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX;
46unsigned long __read_mostly tracing_thresh;
47
48/*
49 * We need to change this state when a selftest is running.

--- 276 unchanged lines hidden (view full) ---

326 data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
327 data->policy = tsk->policy;
328 data->rt_priority = tsk->rt_priority;
329
330 /* record this tasks comm */
331 tracing_record_cmdline(current);
332}
333
333/**
334 * trace_seq_printf - sequence printing of trace information
335 * @s: trace sequence descriptor
336 * @fmt: printf format string
337 *
338 * The tracer may use either sequence operations or its own
339 * copy to user routines. To simplify formating of a trace
340 * trace_seq_printf is used to store strings into a special
341 * buffer (@s). Then the output may be either used by
342 * the sequencer or pulled into another buffer.
343 */
344int
345trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
346{
347 int len = (PAGE_SIZE - 1) - s->len;
348 va_list ap;
349 int ret;
350
351 if (!len)
352 return 0;
353
354 va_start(ap, fmt);
355 ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
356 va_end(ap);
357
358 /* If we can't write it all, don't bother writing anything */
359 if (ret >= len)
360 return 0;
361
362 s->len += ret;
363
364 return len;
365}
366
367/**
368 * trace_seq_puts - trace sequence printing of simple string
369 * @s: trace sequence descriptor
370 * @str: simple string to record
371 *
372 * The tracer may use either the sequence operations or its own
373 * copy to user routines. This function records a simple string
374 * into a special buffer (@s) for later retrieval by a sequencer
375 * or other mechanism.
376 */
377static int
378trace_seq_puts(struct trace_seq *s, const char *str)
379{
380 int len = strlen(str);
381
382 if (len > ((PAGE_SIZE - 1) - s->len))
383 return 0;
384
385 memcpy(s->buffer + s->len, str, len);
386 s->len += len;
387
388 return len;
389}
390
391static int
392trace_seq_putc(struct trace_seq *s, unsigned char c)
393{
394 if (s->len >= (PAGE_SIZE - 1))
395 return 0;
396
397 s->buffer[s->len++] = c;
398
399 return 1;
400}
401
402static int
403trace_seq_putmem(struct trace_seq *s, void *mem, size_t len)
404{
405 if (len > ((PAGE_SIZE - 1) - s->len))
406 return 0;
407
408 memcpy(s->buffer + s->len, mem, len);
409 s->len += len;
410
411 return len;
412}
413
414#define MAX_MEMHEX_BYTES 8
415#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)
416
417static int
418trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len)
419{
420 unsigned char hex[HEX_CHARS];
421 unsigned char *data = mem;
422 int i, j;
423
424#ifdef __BIG_ENDIAN
425 for (i = 0, j = 0; i < len; i++) {
426#else
427 for (i = len-1, j = 0; i >= 0; i--) {
428#endif
429 hex[j++] = hex_asc_hi(data[i]);
430 hex[j++] = hex_asc_lo(data[i]);
431 }
432 hex[j++] = ' ';
433
434 return trace_seq_putmem(s, hex, j);
435}
436
437static int
438trace_seq_path(struct trace_seq *s, struct path *path)
439{
440 unsigned char *p;
441
442 if (s->len >= (PAGE_SIZE - 1))
443 return 0;
444 p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
445 if (!IS_ERR(p)) {
446 p = mangle_path(s->buffer + s->len, p, "\n");
447 if (p) {
448 s->len = p - s->buffer;
449 return 1;
450 }
451 } else {
452 s->buffer[s->len++] = '?';
453 return 1;
454 }
455
456 return 0;
457}
458
459static void
460trace_seq_reset(struct trace_seq *s)
461{
462 s->len = 0;
463 s->readpos = 0;
464}
465
466ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)

--- 1001 unchanged lines hidden (view full) ---

1468}
1469
1470static void s_stop(struct seq_file *m, void *p)
1471{
1472 atomic_dec(&trace_record_cmdline_disabled);
1473 mutex_unlock(&trace_types_lock);
1474}
1475
334static void
335trace_seq_reset(struct trace_seq *s)
336{
337 s->len = 0;
338 s->readpos = 0;
339}
340
341ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)

--- 1001 unchanged lines hidden (view full) ---

1343}
1344
1345static void s_stop(struct seq_file *m, void *p)
1346{
1347 atomic_dec(&trace_record_cmdline_disabled);
1348 mutex_unlock(&trace_types_lock);
1349}
1350
1476#ifdef CONFIG_KRETPROBES
1477static inline const char *kretprobed(const char *name)
1478{
1479 static const char tramp_name[] = "kretprobe_trampoline";
1480 int size = sizeof(tramp_name);
1481
1482 if (strncmp(tramp_name, name, size) == 0)
1483 return "[unknown/kretprobe'd]";
1484 return name;
1485}
1486#else
1487static inline const char *kretprobed(const char *name)
1488{
1489 return name;
1490}
1491#endif /* CONFIG_KRETPROBES */
1492
1493static int
1494seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
1495{
1496#ifdef CONFIG_KALLSYMS
1497 char str[KSYM_SYMBOL_LEN];
1498 const char *name;
1499
1500 kallsyms_lookup(address, NULL, NULL, NULL, str);
1501
1502 name = kretprobed(str);
1503
1504 return trace_seq_printf(s, fmt, name);
1505#endif
1506 return 1;
1507}
1508
1509static int
1510seq_print_sym_offset(struct trace_seq *s, const char *fmt,
1511 unsigned long address)
1512{
1513#ifdef CONFIG_KALLSYMS
1514 char str[KSYM_SYMBOL_LEN];
1515 const char *name;
1516
1517 sprint_symbol(str, address);
1518 name = kretprobed(str);
1519
1520 return trace_seq_printf(s, fmt, name);
1521#endif
1522 return 1;
1523}
1524
1525#ifndef CONFIG_64BIT
1526# define IP_FMT "%08lx"
1527#else
1528# define IP_FMT "%016lx"
1529#endif
1530
1531int
1532seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
1533{
1534 int ret;
1535
1536 if (!ip)
1537 return trace_seq_printf(s, "0");
1538
1539 if (sym_flags & TRACE_ITER_SYM_OFFSET)
1540 ret = seq_print_sym_offset(s, "%s", ip);
1541 else
1542 ret = seq_print_sym_short(s, "%s", ip);
1543
1544 if (!ret)
1545 return 0;
1546
1547 if (sym_flags & TRACE_ITER_SYM_ADDR)
1548 ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
1549 return ret;
1550}
1551
1552static inline int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
1553 unsigned long ip, unsigned long sym_flags)
1554{
1555 struct file *file = NULL;
1556 unsigned long vmstart = 0;
1557 int ret = 1;
1558
1559 if (mm) {
1560 const struct vm_area_struct *vma;
1561
1562 down_read(&mm->mmap_sem);
1563 vma = find_vma(mm, ip);
1564 if (vma) {
1565 file = vma->vm_file;
1566 vmstart = vma->vm_start;
1567 }
1568 if (file) {
1569 ret = trace_seq_path(s, &file->f_path);
1570 if (ret)
1571 ret = trace_seq_printf(s, "[+0x%lx]", ip - vmstart);
1572 }
1573 up_read(&mm->mmap_sem);
1574 }
1575 if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file))
1576 ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
1577 return ret;
1578}
1579
1580static int
1581seq_print_userip_objs(const struct userstack_entry *entry, struct trace_seq *s,
1582 unsigned long sym_flags)
1583{
1584 struct mm_struct *mm = NULL;
1585 int ret = 1;
1586 unsigned int i;
1587
1588 if (trace_flags & TRACE_ITER_SYM_USEROBJ) {
1589 struct task_struct *task;
1590 /*
1591 * we do the lookup on the thread group leader,
1592 * since individual threads might have already quit!
1593 */
1594 rcu_read_lock();
1595 task = find_task_by_vpid(entry->ent.tgid);
1596 if (task)
1597 mm = get_task_mm(task);
1598 rcu_read_unlock();
1599 }
1600
1601 for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1602 unsigned long ip = entry->caller[i];
1603
1604 if (ip == ULONG_MAX || !ret)
1605 break;
1606 if (i && ret)
1607 ret = trace_seq_puts(s, " <- ");
1608 if (!ip) {
1609 if (ret)
1610 ret = trace_seq_puts(s, "??");
1611 continue;
1612 }
1613 if (!ret)
1614 break;
1615 if (ret)
1616 ret = seq_print_user_ip(s, mm, ip, sym_flags);
1617 }
1618
1619 if (mm)
1620 mmput(mm);
1621 return ret;
1622}
1623
1624static void print_lat_help_header(struct seq_file *m)
1625{
1626 seq_puts(m, "# _------=> CPU# \n");
1627 seq_puts(m, "# / _-----=> irqs-off \n");
1628 seq_puts(m, "# | / _----=> need-resched \n");
1629 seq_puts(m, "# || / _---=> hardirq/softirq \n");
1630 seq_puts(m, "# ||| / _--=> preempt-depth \n");
1631 seq_puts(m, "# |||| / \n");

--- 2189 unchanged lines hidden ---
1351static void print_lat_help_header(struct seq_file *m)
1352{
1353 seq_puts(m, "# _------=> CPU# \n");
1354 seq_puts(m, "# / _-----=> irqs-off \n");
1355 seq_puts(m, "# | / _----=> need-resched \n");
1356 seq_puts(m, "# || / _---=> hardirq/softirq \n");
1357 seq_puts(m, "# ||| / _--=> preempt-depth \n");
1358 seq_puts(m, "# |||| / \n");

--- 2189 unchanged lines hidden ---