aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-10 07:58:28 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-10 07:58:28 -0500
commitae216dd239765afd592f65d94d8430244cf77ed1 (patch)
treea8e203cd9260be48d07e1484f87023d7d3dbae64 /kernel
parentf9915bfef3c64ea0b0b960dd1b999b584a7ef460 (diff)
parent34cd4998d38f9bd04f34b78a7cb0c7f1bee00bd9 (diff)
Merge branch 'tip/tracing/ftrace' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into tracing/ftrace
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c219
-rw-r--r--kernel/trace/trace.h6
2 files changed, 196 insertions, 29 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 5b1e9a9e9906..d89821283b47 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -31,6 +31,7 @@
31#include <linux/fs.h> 31#include <linux/fs.h>
32#include <linux/kprobes.h> 32#include <linux/kprobes.h>
33#include <linux/writeback.h> 33#include <linux/writeback.h>
34#include <linux/splice.h>
34 35
35#include <linux/stacktrace.h> 36#include <linux/stacktrace.h>
36#include <linux/ring_buffer.h> 37#include <linux/ring_buffer.h>
@@ -364,6 +365,25 @@ ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)
364 return cnt; 365 return cnt;
365} 366}
366 367
368ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
369{
370 int len;
371 void *ret;
372
373 if (s->len <= s->readpos)
374 return -EBUSY;
375
376 len = s->len - s->readpos;
377 if (cnt > len)
378 cnt = len;
379 ret = memcpy(buf, s->buffer + s->readpos, cnt);
380 if (!ret)
381 return -EFAULT;
382
383 s->readpos += len;
384 return cnt;
385}
386
367static void 387static void
368trace_print_seq(struct seq_file *m, struct trace_seq *s) 388trace_print_seq(struct seq_file *m, struct trace_seq *s)
369{ 389{
@@ -2368,37 +2388,15 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table)
2368 } 2388 }
2369} 2389}
2370 2390
2371/* 2391/* Must be called with trace_types_lock mutex held. */
2372 * Consumer reader. 2392static int tracing_wait_pipe(struct file *filp)
2373 */
2374static ssize_t
2375tracing_read_pipe(struct file *filp, char __user *ubuf,
2376 size_t cnt, loff_t *ppos)
2377{ 2393{
2378 struct trace_iterator *iter = filp->private_data; 2394 struct trace_iterator *iter = filp->private_data;
2379 ssize_t sret;
2380
2381 /* return any leftover data */
2382 sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
2383 if (sret != -EBUSY)
2384 return sret;
2385
2386 trace_seq_reset(&iter->seq);
2387 2395
2388 mutex_lock(&trace_types_lock);
2389 if (iter->trace->read) {
2390 sret = iter->trace->read(iter, filp, ubuf, cnt, ppos);
2391 if (sret)
2392 goto out;
2393 }
2394
2395waitagain:
2396 sret = 0;
2397 while (trace_empty(iter)) { 2396 while (trace_empty(iter)) {
2398 2397
2399 if ((filp->f_flags & O_NONBLOCK)) { 2398 if ((filp->f_flags & O_NONBLOCK)) {
2400 sret = -EAGAIN; 2399 return -EAGAIN;
2401 goto out;
2402 } 2400 }
2403 2401
2404 /* 2402 /*
@@ -2423,12 +2421,11 @@ waitagain:
2423 iter->tr->waiter = NULL; 2421 iter->tr->waiter = NULL;
2424 2422
2425 if (signal_pending(current)) { 2423 if (signal_pending(current)) {
2426 sret = -EINTR; 2424 return -EINTR;
2427 goto out;
2428 } 2425 }
2429 2426
2430 if (iter->trace != current_trace) 2427 if (iter->trace != current_trace)
2431 goto out; 2428 return 0;
2432 2429
2433 /* 2430 /*
2434 * We block until we read something and tracing is disabled. 2431 * We block until we read something and tracing is disabled.
@@ -2445,9 +2442,43 @@ waitagain:
2445 continue; 2442 continue;
2446 } 2443 }
2447 2444
2445 return 1;
2446}
2447
2448/*
2449 * Consumer reader.
2450 */
2451static ssize_t
2452tracing_read_pipe(struct file *filp, char __user *ubuf,
2453 size_t cnt, loff_t *ppos)
2454{
2455 struct trace_iterator *iter = filp->private_data;
2456 ssize_t sret;
2457
2458 /* return any leftover data */
2459 sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
2460 if (sret != -EBUSY)
2461 return sret;
2462
2463 trace_seq_reset(&iter->seq);
2464
2465 mutex_lock(&trace_types_lock);
2466 if (iter->trace->read) {
2467 sret = iter->trace->read(iter, filp, ubuf, cnt, ppos);
2468 if (sret)
2469 goto out;
2470 }
2471
2472waitagain:
2473 sret = tracing_wait_pipe(filp);
2474 if (sret <= 0)
2475 goto out;
2476
2448 /* stop when tracing is finished */ 2477 /* stop when tracing is finished */
2449 if (trace_empty(iter)) 2478 if (trace_empty(iter)) {
2479 sret = 0;
2450 goto out; 2480 goto out;
2481 }
2451 2482
2452 if (cnt >= PAGE_SIZE) 2483 if (cnt >= PAGE_SIZE)
2453 cnt = PAGE_SIZE - 1; 2484 cnt = PAGE_SIZE - 1;
@@ -2493,6 +2524,135 @@ out:
2493 return sret; 2524 return sret;
2494} 2525}
2495 2526
2527static void tracing_pipe_buf_release(struct pipe_inode_info *pipe,
2528 struct pipe_buffer *buf)
2529{
2530 __free_page(buf->page);
2531}
2532
2533static void tracing_spd_release_pipe(struct splice_pipe_desc *spd,
2534 unsigned int idx)
2535{
2536 __free_page(spd->pages[idx]);
2537}
2538
2539static struct pipe_buf_operations tracing_pipe_buf_ops = {
2540 .can_merge = 0,
2541 .map = generic_pipe_buf_map,
2542 .unmap = generic_pipe_buf_unmap,
2543 .confirm = generic_pipe_buf_confirm,
2544 .release = tracing_pipe_buf_release,
2545 .steal = generic_pipe_buf_steal,
2546 .get = generic_pipe_buf_get,
2547};
2548
2549static size_t
2550tracing_fill_pipe_page(struct page *pages, size_t rem,
2551 struct trace_iterator *iter)
2552{
2553 size_t count;
2554 int ret;
2555
2556 /* Seq buffer is page-sized, exactly what we need. */
2557 for (;;) {
2558 count = iter->seq.len;
2559 ret = print_trace_line(iter);
2560 count = iter->seq.len - count;
2561 if (rem < count) {
2562 rem = 0;
2563 iter->seq.len -= count;
2564 break;
2565 }
2566 if (ret == TRACE_TYPE_PARTIAL_LINE) {
2567 iter->seq.len -= count;
2568 break;
2569 }
2570
2571 trace_consume(iter);
2572 rem -= count;
2573 if (!find_next_entry_inc(iter)) {
2574 rem = 0;
2575 iter->ent = NULL;
2576 break;
2577 }
2578 }
2579
2580 return rem;
2581}
2582
2583static ssize_t tracing_splice_read_pipe(struct file *filp,
2584 loff_t *ppos,
2585 struct pipe_inode_info *pipe,
2586 size_t len,
2587 unsigned int flags)
2588{
2589 struct page *pages[PIPE_BUFFERS];
2590 struct partial_page partial[PIPE_BUFFERS];
2591 struct trace_iterator *iter = filp->private_data;
2592 struct splice_pipe_desc spd = {
2593 .pages = pages,
2594 .partial = partial,
2595 .nr_pages = 0, /* This gets updated below. */
2596 .flags = flags,
2597 .ops = &tracing_pipe_buf_ops,
2598 .spd_release = tracing_spd_release_pipe,
2599 };
2600 ssize_t ret;
2601 size_t rem;
2602 unsigned int i;
2603
2604 mutex_lock(&trace_types_lock);
2605
2606 if (iter->trace->splice_read) {
2607 ret = iter->trace->splice_read(iter, filp,
2608 ppos, pipe, len, flags);
2609 if (ret)
2610 goto out_err;
2611 }
2612
2613 ret = tracing_wait_pipe(filp);
2614 if (ret <= 0)
2615 goto out_err;
2616
2617 if (!iter->ent && !find_next_entry_inc(iter)) {
2618 ret = -EFAULT;
2619 goto out_err;
2620 }
2621
2622 /* Fill as many pages as possible. */
2623 for (i = 0, rem = len; i < PIPE_BUFFERS && rem; i++) {
2624 pages[i] = alloc_page(GFP_KERNEL);
2625 if (!pages[i])
2626 break;
2627
2628 rem = tracing_fill_pipe_page(pages[i], rem, iter);
2629
2630 /* Copy the data into the page, so we can start over. */
2631 ret = trace_seq_to_buffer(&iter->seq,
2632 page_address(pages[i]),
2633 iter->seq.len);
2634 if (ret < 0) {
2635 __free_page(pages[i]);
2636 break;
2637 }
2638 partial[i].offset = 0;
2639 partial[i].len = iter->seq.len;
2640
2641 trace_seq_reset(&iter->seq);
2642 }
2643
2644 mutex_unlock(&trace_types_lock);
2645
2646 spd.nr_pages = i;
2647
2648 return splice_to_pipe(pipe, &spd);
2649
2650out_err:
2651 mutex_unlock(&trace_types_lock);
2652
2653 return ret;
2654}
2655
2496static ssize_t 2656static ssize_t
2497tracing_entries_read(struct file *filp, char __user *ubuf, 2657tracing_entries_read(struct file *filp, char __user *ubuf,
2498 size_t cnt, loff_t *ppos) 2658 size_t cnt, loff_t *ppos)
@@ -2656,6 +2816,7 @@ static struct file_operations tracing_pipe_fops = {
2656 .open = tracing_open_pipe, 2816 .open = tracing_open_pipe,
2657 .poll = tracing_poll_pipe, 2817 .poll = tracing_poll_pipe,
2658 .read = tracing_read_pipe, 2818 .read = tracing_read_pipe,
2819 .splice_read = tracing_splice_read_pipe,
2659 .release = tracing_release_pipe, 2820 .release = tracing_release_pipe,
2660}; 2821};
2661 2822
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 7b0518adf6d7..dbff0207b213 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -353,6 +353,12 @@ struct tracer {
353 ssize_t (*read)(struct trace_iterator *iter, 353 ssize_t (*read)(struct trace_iterator *iter,
354 struct file *filp, char __user *ubuf, 354 struct file *filp, char __user *ubuf,
355 size_t cnt, loff_t *ppos); 355 size_t cnt, loff_t *ppos);
356 ssize_t (*splice_read)(struct trace_iterator *iter,
357 struct file *filp,
358 loff_t *ppos,
359 struct pipe_inode_info *pipe,
360 size_t len,
361 unsigned int flags);
356#ifdef CONFIG_FTRACE_STARTUP_TEST 362#ifdef CONFIG_FTRACE_STARTUP_TEST
357 int (*selftest)(struct tracer *trace, 363 int (*selftest)(struct tracer *trace,
358 struct trace_array *tr); 364 struct trace_array *tr);