diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 958c4d77a67b..d041578affd0 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/percpu.h> | 24 | #include <linux/percpu.h> |
25 | #include <linux/ctype.h> | 25 | #include <linux/ctype.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/poll.h> | ||
27 | #include <linux/gfp.h> | 28 | #include <linux/gfp.h> |
28 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
29 | 30 | ||
@@ -63,6 +64,7 @@ static struct tracer *current_trace __read_mostly; | |||
63 | static int max_tracer_type_len; | 64 | static int max_tracer_type_len; |
64 | 65 | ||
65 | static DEFINE_MUTEX(trace_types_lock); | 66 | static DEFINE_MUTEX(trace_types_lock); |
67 | static DECLARE_WAIT_QUEUE_HEAD (trace_wait); | ||
66 | 68 | ||
67 | #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct trace_entry)) | 69 | #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct trace_entry)) |
68 | 70 | ||
@@ -105,6 +107,7 @@ enum trace_iterator_flags { | |||
105 | TRACE_ITER_RAW = 0x10, | 107 | TRACE_ITER_RAW = 0x10, |
106 | TRACE_ITER_HEX = 0x20, | 108 | TRACE_ITER_HEX = 0x20, |
107 | TRACE_ITER_BIN = 0x40, | 109 | TRACE_ITER_BIN = 0x40, |
110 | TRACE_ITER_BLOCK = 0x80, | ||
108 | }; | 111 | }; |
109 | 112 | ||
110 | #define TRACE_ITER_SYM_MASK \ | 113 | #define TRACE_ITER_SYM_MASK \ |
@@ -119,6 +122,7 @@ static const char *trace_options[] = { | |||
119 | "raw", | 122 | "raw", |
120 | "hex", | 123 | "hex", |
121 | "bin", | 124 | "bin", |
125 | "block", | ||
122 | NULL | 126 | NULL |
123 | }; | 127 | }; |
124 | 128 | ||
@@ -650,6 +654,9 @@ __ftrace(struct trace_array *tr, struct trace_array_cpu *data, | |||
650 | entry->fn.ip = ip; | 654 | entry->fn.ip = ip; |
651 | entry->fn.parent_ip = parent_ip; | 655 | entry->fn.parent_ip = parent_ip; |
652 | spin_unlock_irqrestore(&data->lock, irq_flags); | 656 | spin_unlock_irqrestore(&data->lock, irq_flags); |
657 | |||
658 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
659 | wake_up (&trace_wait); | ||
653 | } | 660 | } |
654 | 661 | ||
655 | notrace void | 662 | notrace void |
@@ -675,6 +682,9 @@ trace_special(struct trace_array *tr, struct trace_array_cpu *data, | |||
675 | entry->special.arg2 = arg2; | 682 | entry->special.arg2 = arg2; |
676 | entry->special.arg3 = arg3; | 683 | entry->special.arg3 = arg3; |
677 | spin_unlock_irqrestore(&data->lock, irq_flags); | 684 | spin_unlock_irqrestore(&data->lock, irq_flags); |
685 | |||
686 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
687 | wake_up (&trace_wait); | ||
678 | } | 688 | } |
679 | 689 | ||
680 | notrace void | 690 | notrace void |
@@ -696,6 +706,9 @@ tracing_sched_switch_trace(struct trace_array *tr, | |||
696 | entry->ctx.next_pid = next->pid; | 706 | entry->ctx.next_pid = next->pid; |
697 | entry->ctx.next_prio = next->prio; | 707 | entry->ctx.next_prio = next->prio; |
698 | spin_unlock_irqrestore(&data->lock, irq_flags); | 708 | spin_unlock_irqrestore(&data->lock, irq_flags); |
709 | |||
710 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
711 | wake_up (&trace_wait); | ||
699 | } | 712 | } |
700 | 713 | ||
701 | #ifdef CONFIG_FTRACE | 714 | #ifdef CONFIG_FTRACE |
@@ -1765,7 +1778,6 @@ static struct file_operations tracing_readme_fops = { | |||
1765 | .read = tracing_readme_read, | 1778 | .read = tracing_readme_read, |
1766 | }; | 1779 | }; |
1767 | 1780 | ||
1768 | |||
1769 | static ssize_t | 1781 | static ssize_t |
1770 | tracing_ctrl_read(struct file *filp, char __user *ubuf, | 1782 | tracing_ctrl_read(struct file *filp, char __user *ubuf, |
1771 | size_t cnt, loff_t *ppos) | 1783 | size_t cnt, loff_t *ppos) |
@@ -1953,6 +1965,28 @@ static int tracing_release_pipe(struct inode *inode, struct file *file) | |||
1953 | return 0; | 1965 | return 0; |
1954 | } | 1966 | } |
1955 | 1967 | ||
1968 | static unsigned int | ||
1969 | tracing_poll_pipe(struct file *filp, poll_table *poll_table) | ||
1970 | { | ||
1971 | struct trace_iterator *iter = filp->private_data; | ||
1972 | |||
1973 | if (trace_flags & TRACE_ITER_BLOCK) { | ||
1974 | /* | ||
1975 | * Always select as readable when in blocking mode | ||
1976 | */ | ||
1977 | return POLLIN | POLLRDNORM; | ||
1978 | } | ||
1979 | else { | ||
1980 | if (!trace_empty(iter)) | ||
1981 | return POLLIN | POLLRDNORM; | ||
1982 | poll_wait(filp, &trace_wait, poll_table); | ||
1983 | if (!trace_empty(iter)) | ||
1984 | return POLLIN | POLLRDNORM; | ||
1985 | |||
1986 | return 0; | ||
1987 | } | ||
1988 | } | ||
1989 | |||
1956 | /* | 1990 | /* |
1957 | * Consumer reader. | 1991 | * Consumer reader. |
1958 | */ | 1992 | */ |
@@ -1991,6 +2025,8 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
1991 | start = 0; | 2025 | start = 0; |
1992 | 2026 | ||
1993 | while (trace_empty(iter)) { | 2027 | while (trace_empty(iter)) { |
2028 | if (!(trace_flags & TRACE_ITER_BLOCK)) | ||
2029 | return -EWOULDBLOCK; | ||
1994 | /* | 2030 | /* |
1995 | * This is a make-shift waitqueue. The reason we don't use | 2031 | * This is a make-shift waitqueue. The reason we don't use |
1996 | * an actual wait queue is because: | 2032 | * an actual wait queue is because: |
@@ -2134,6 +2170,7 @@ static struct file_operations set_tracer_fops = { | |||
2134 | 2170 | ||
2135 | static struct file_operations tracing_pipe_fops = { | 2171 | static struct file_operations tracing_pipe_fops = { |
2136 | .open = tracing_open_pipe, | 2172 | .open = tracing_open_pipe, |
2173 | .poll = tracing_poll_pipe, | ||
2137 | .read = tracing_read_pipe, | 2174 | .read = tracing_read_pipe, |
2138 | .release = tracing_release_pipe, | 2175 | .release = tracing_release_pipe, |
2139 | }; | 2176 | }; |