From ff98781bab2735e6c89793034173e0cb5007a7e5 Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 9 Feb 2009 08:15:55 +0200 Subject: [PATCH] tracing: Move pipe waiting code out of tracing_read_pipe(). This moves the pipe waiting code from tracing_read_pipe() into tracing_wait_pipe(), which is useful to implement other fops, like splice_read. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 115 ++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 52 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9e29fdb0dfe5..11fde0ad9cb6 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2388,6 +2388,63 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table) } } +/* Must be called with trace_types_lock mutex held. */ +static int tracing_wait_pipe(struct file *filp) +{ + struct trace_iterator *iter = filp->private_data; + + while (trace_empty(iter)) { + + if ((filp->f_flags & O_NONBLOCK)) { + return -EAGAIN; + } + + /* + * This is a make-shift waitqueue. The reason we don't use + * an actual wait queue is because: + * 1) we only ever have one waiter + * 2) the tracing, traces all functions, we don't want + * the overhead of calling wake_up and friends + * (and tracing them too) + * Anyway, this is really very primitive wakeup. + */ + set_current_state(TASK_INTERRUPTIBLE); + iter->tr->waiter = current; + + mutex_unlock(&trace_types_lock); + + /* sleep for 100 msecs, and try again. */ + schedule_timeout(HZ/10); + + mutex_lock(&trace_types_lock); + + iter->tr->waiter = NULL; + + if (signal_pending(current)) { + return -EINTR; + } + + if (iter->trace != current_trace) + return 0; + + /* + * We block until we read something and tracing is disabled. + * We still block if tracing is disabled, but we have never + * read anything. This allows a user to cat this file, and + * then enable tracing. But after we have read something, + * we give an EOF when tracing is again disabled. + * + * iter->pos will be 0 if we haven't read anything. + */ + if (!tracer_enabled && iter->pos) + break; + + continue; + } + + return 1; +} + /* * Consumer reader. */ @@ -2413,61 +2470,15 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, } waitagain: - sret = 0; - while (trace_empty(iter)) { - - if ((filp->f_flags & O_NONBLOCK)) { - sret = -EAGAIN; - goto out; - } - - /* - * This is a make-shift waitqueue. The reason we don't use - * an actual wait queue is because: - * 1) we only ever have one waiter - * 2) the tracing, traces all functions, we don't want - * the overhead of calling wake_up and friends - * (and tracing them too) - * Anyway, this is really very primitive wakeup. - */ - set_current_state(TASK_INTERRUPTIBLE); - iter->tr->waiter = current; - - mutex_unlock(&trace_types_lock); - - /* sleep for 100 msecs, and try again. */ - schedule_timeout(HZ/10); - - mutex_lock(&trace_types_lock); - - iter->tr->waiter = NULL; - - if (signal_pending(current)) { - sret = -EINTR; - goto out; - } - - if (iter->trace != current_trace) - goto out; - - /* - * We block until we read something and tracing is disabled. - * We still block if tracing is disabled, but we have never - * read anything. This allows a user to cat this file, and - * then enable tracing. But after we have read something, - * we give an EOF when tracing is again disabled. - * - * iter->pos will be 0 if we haven't read anything. - */ - if (!tracer_enabled && iter->pos) - break; - - continue; - } + sret = tracing_wait_pipe(filp); + if (sret <= 0) + goto out; /* stop when tracing is finished */ - if (trace_empty(iter)) + if (trace_empty(iter)) { + sret = 0; goto out; + } if (cnt >= PAGE_SIZE) cnt = PAGE_SIZE - 1;