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 --- |