diff options
author | Steven Rostedt <srostedt@redhat.com> | 2013-02-28 09:17:16 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-03-15 00:34:49 -0400 |
commit | cc60cdc952be09bca5b0bff9fefc7aa6185c3049 (patch) | |
tree | d16c601f5848b556b3f02487a74af0835ede82fa /kernel/trace | |
parent | 189e5784f6c5e001a84127b83f03bc76a8bfb1ec (diff) |
tracing: Fix polling on trace_pipe_raw
The trace_pipe_raw never implemented polling and this was casing
issues for several utilities. This is now implemented.
Blocked reads still are on the TODO list.
Reported-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Tested-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.c | 78 |
1 files changed, 51 insertions, 27 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 598a7aa7d0ae..4a6e461273a9 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -3555,10 +3555,8 @@ static int tracing_release_pipe(struct inode *inode, struct file *file) | |||
3555 | } | 3555 | } |
3556 | 3556 | ||
3557 | static unsigned int | 3557 | static unsigned int |
3558 | tracing_poll_pipe(struct file *filp, poll_table *poll_table) | 3558 | trace_poll(struct trace_iterator *iter, struct file *filp, poll_table *poll_table) |
3559 | { | 3559 | { |
3560 | struct trace_iterator *iter = filp->private_data; | ||
3561 | |||
3562 | if (trace_flags & TRACE_ITER_BLOCK) { | 3560 | if (trace_flags & TRACE_ITER_BLOCK) { |
3563 | /* | 3561 | /* |
3564 | * Always select as readable when in blocking mode | 3562 | * Always select as readable when in blocking mode |
@@ -3567,6 +3565,7 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table) | |||
3567 | } else { | 3565 | } else { |
3568 | if (!trace_empty(iter)) | 3566 | if (!trace_empty(iter)) |
3569 | return POLLIN | POLLRDNORM; | 3567 | return POLLIN | POLLRDNORM; |
3568 | trace_wakeup_needed = true; | ||
3570 | poll_wait(filp, &trace_wait, poll_table); | 3569 | poll_wait(filp, &trace_wait, poll_table); |
3571 | if (!trace_empty(iter)) | 3570 | if (!trace_empty(iter)) |
3572 | return POLLIN | POLLRDNORM; | 3571 | return POLLIN | POLLRDNORM; |
@@ -3575,6 +3574,14 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table) | |||
3575 | } | 3574 | } |
3576 | } | 3575 | } |
3577 | 3576 | ||
3577 | static unsigned int | ||
3578 | tracing_poll_pipe(struct file *filp, poll_table *poll_table) | ||
3579 | { | ||
3580 | struct trace_iterator *iter = filp->private_data; | ||
3581 | |||
3582 | return trace_poll(iter, filp, poll_table); | ||
3583 | } | ||
3584 | |||
3578 | /* | 3585 | /* |
3579 | * This is a make-shift waitqueue. | 3586 | * This is a make-shift waitqueue. |
3580 | * A tracer might use this callback on some rare cases: | 3587 | * A tracer might use this callback on some rare cases: |
@@ -4362,9 +4369,8 @@ static const struct file_operations snapshot_fops = { | |||
4362 | #endif /* CONFIG_TRACER_SNAPSHOT */ | 4369 | #endif /* CONFIG_TRACER_SNAPSHOT */ |
4363 | 4370 | ||
4364 | struct ftrace_buffer_info { | 4371 | struct ftrace_buffer_info { |
4365 | struct trace_array *tr; | 4372 | struct trace_iterator iter; |
4366 | void *spare; | 4373 | void *spare; |
4367 | int cpu; | ||
4368 | unsigned int read; | 4374 | unsigned int read; |
4369 | }; | 4375 | }; |
4370 | 4376 | ||
@@ -4381,22 +4387,32 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp) | |||
4381 | if (!info) | 4387 | if (!info) |
4382 | return -ENOMEM; | 4388 | return -ENOMEM; |
4383 | 4389 | ||
4384 | info->tr = tr; | 4390 | info->iter.tr = tr; |
4385 | info->cpu = tc->cpu; | 4391 | info->iter.cpu_file = tc->cpu; |
4386 | info->spare = NULL; | 4392 | info->spare = NULL; |
4387 | /* Force reading ring buffer for first read */ | 4393 | /* Force reading ring buffer for first read */ |
4388 | info->read = (unsigned int)-1; | 4394 | info->read = (unsigned int)-1; |
4389 | 4395 | ||
4390 | filp->private_data = info; | 4396 | filp->private_data = info; |
4391 | 4397 | ||
4392 | return nonseekable_open(inode, filp); | 4398 | return nonseekable_open(inode, filp); |
4393 | } | 4399 | } |
4394 | 4400 | ||
4401 | static unsigned int | ||
4402 | tracing_buffers_poll(struct file *filp, poll_table *poll_table) | ||
4403 | { | ||
4404 | struct ftrace_buffer_info *info = filp->private_data; | ||
4405 | struct trace_iterator *iter = &info->iter; | ||
4406 | |||
4407 | return trace_poll(iter, filp, poll_table); | ||
4408 | } | ||
4409 | |||
4395 | static ssize_t | 4410 | static ssize_t |
4396 | tracing_buffers_read(struct file *filp, char __user *ubuf, | 4411 | tracing_buffers_read(struct file *filp, char __user *ubuf, |
4397 | size_t count, loff_t *ppos) | 4412 | size_t count, loff_t *ppos) |
4398 | { | 4413 | { |
4399 | struct ftrace_buffer_info *info = filp->private_data; | 4414 | struct ftrace_buffer_info *info = filp->private_data; |
4415 | struct trace_iterator *iter = &info->iter; | ||
4400 | ssize_t ret; | 4416 | ssize_t ret; |
4401 | size_t size; | 4417 | size_t size; |
4402 | 4418 | ||
@@ -4404,7 +4420,7 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, | |||
4404 | return 0; | 4420 | return 0; |
4405 | 4421 | ||
4406 | if (!info->spare) | 4422 | if (!info->spare) |
4407 | info->spare = ring_buffer_alloc_read_page(info->tr->buffer, info->cpu); | 4423 | info->spare = ring_buffer_alloc_read_page(iter->tr->buffer, iter->cpu_file); |
4408 | if (!info->spare) | 4424 | if (!info->spare) |
4409 | return -ENOMEM; | 4425 | return -ENOMEM; |
4410 | 4426 | ||
@@ -4412,12 +4428,12 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, | |||
4412 | if (info->read < PAGE_SIZE) | 4428 | if (info->read < PAGE_SIZE) |
4413 | goto read; | 4429 | goto read; |
4414 | 4430 | ||
4415 | trace_access_lock(info->cpu); | 4431 | trace_access_lock(iter->cpu_file); |
4416 | ret = ring_buffer_read_page(info->tr->buffer, | 4432 | ret = ring_buffer_read_page(iter->tr->buffer, |
4417 | &info->spare, | 4433 | &info->spare, |
4418 | count, | 4434 | count, |
4419 | info->cpu, 0); | 4435 | iter->cpu_file, 0); |
4420 | trace_access_unlock(info->cpu); | 4436 | trace_access_unlock(iter->cpu_file); |
4421 | if (ret < 0) | 4437 | if (ret < 0) |
4422 | return 0; | 4438 | return 0; |
4423 | 4439 | ||
@@ -4442,9 +4458,10 @@ read: | |||
4442 | static int tracing_buffers_release(struct inode *inode, struct file *file) | 4458 | static int tracing_buffers_release(struct inode *inode, struct file *file) |
4443 | { | 4459 | { |
4444 | struct ftrace_buffer_info *info = file->private_data; | 4460 | struct ftrace_buffer_info *info = file->private_data; |
4461 | struct trace_iterator *iter = &info->iter; | ||
4445 | 4462 | ||
4446 | if (info->spare) | 4463 | if (info->spare) |
4447 | ring_buffer_free_read_page(info->tr->buffer, info->spare); | 4464 | ring_buffer_free_read_page(iter->tr->buffer, info->spare); |
4448 | kfree(info); | 4465 | kfree(info); |
4449 | 4466 | ||
4450 | return 0; | 4467 | return 0; |
@@ -4511,6 +4528,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
4511 | unsigned int flags) | 4528 | unsigned int flags) |
4512 | { | 4529 | { |
4513 | struct ftrace_buffer_info *info = file->private_data; | 4530 | struct ftrace_buffer_info *info = file->private_data; |
4531 | struct trace_iterator *iter = &info->iter; | ||
4514 | struct partial_page partial_def[PIPE_DEF_BUFFERS]; | 4532 | struct partial_page partial_def[PIPE_DEF_BUFFERS]; |
4515 | struct page *pages_def[PIPE_DEF_BUFFERS]; | 4533 | struct page *pages_def[PIPE_DEF_BUFFERS]; |
4516 | struct splice_pipe_desc spd = { | 4534 | struct splice_pipe_desc spd = { |
@@ -4541,8 +4559,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
4541 | len &= PAGE_MASK; | 4559 | len &= PAGE_MASK; |
4542 | } | 4560 | } |
4543 | 4561 | ||
4544 | trace_access_lock(info->cpu); | 4562 | again: |
4545 | entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu); | 4563 | trace_access_lock(iter->cpu_file); |
4564 | entries = ring_buffer_entries_cpu(iter->tr->buffer, iter->cpu_file); | ||
4546 | 4565 | ||
4547 | for (i = 0; i < pipe->buffers && len && entries; i++, len -= PAGE_SIZE) { | 4566 | for (i = 0; i < pipe->buffers && len && entries; i++, len -= PAGE_SIZE) { |
4548 | struct page *page; | 4567 | struct page *page; |
@@ -4553,15 +4572,15 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
4553 | break; | 4572 | break; |
4554 | 4573 | ||
4555 | ref->ref = 1; | 4574 | ref->ref = 1; |
4556 | ref->buffer = info->tr->buffer; | 4575 | ref->buffer = iter->tr->buffer; |
4557 | ref->page = ring_buffer_alloc_read_page(ref->buffer, info->cpu); | 4576 | ref->page = ring_buffer_alloc_read_page(ref->buffer, iter->cpu_file); |
4558 | if (!ref->page) { | 4577 | if (!ref->page) { |
4559 | kfree(ref); | 4578 | kfree(ref); |
4560 | break; | 4579 | break; |
4561 | } | 4580 | } |
4562 | 4581 | ||
4563 | r = ring_buffer_read_page(ref->buffer, &ref->page, | 4582 | r = ring_buffer_read_page(ref->buffer, &ref->page, |
4564 | len, info->cpu, 1); | 4583 | len, iter->cpu_file, 1); |
4565 | if (r < 0) { | 4584 | if (r < 0) { |
4566 | ring_buffer_free_read_page(ref->buffer, ref->page); | 4585 | ring_buffer_free_read_page(ref->buffer, ref->page); |
4567 | kfree(ref); | 4586 | kfree(ref); |
@@ -4585,20 +4604,24 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
4585 | spd.nr_pages++; | 4604 | spd.nr_pages++; |
4586 | *ppos += PAGE_SIZE; | 4605 | *ppos += PAGE_SIZE; |
4587 | 4606 | ||
4588 | entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu); | 4607 | entries = ring_buffer_entries_cpu(iter->tr->buffer, iter->cpu_file); |
4589 | } | 4608 | } |
4590 | 4609 | ||
4591 | trace_access_unlock(info->cpu); | 4610 | trace_access_unlock(iter->cpu_file); |
4592 | spd.nr_pages = i; | 4611 | spd.nr_pages = i; |
4593 | 4612 | ||
4594 | /* did we read anything? */ | 4613 | /* did we read anything? */ |
4595 | if (!spd.nr_pages) { | 4614 | if (!spd.nr_pages) { |
4596 | if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) | 4615 | if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) { |
4597 | ret = -EAGAIN; | 4616 | ret = -EAGAIN; |
4598 | else | 4617 | goto out; |
4599 | ret = 0; | 4618 | } |
4600 | /* TODO: block */ | 4619 | default_wait_pipe(iter); |
4601 | goto out; | 4620 | if (signal_pending(current)) { |
4621 | ret = -EINTR; | ||
4622 | goto out; | ||
4623 | } | ||
4624 | goto again; | ||
4602 | } | 4625 | } |
4603 | 4626 | ||
4604 | ret = splice_to_pipe(pipe, &spd); | 4627 | ret = splice_to_pipe(pipe, &spd); |
@@ -4610,6 +4633,7 @@ out: | |||
4610 | static const struct file_operations tracing_buffers_fops = { | 4633 | static const struct file_operations tracing_buffers_fops = { |
4611 | .open = tracing_buffers_open, | 4634 | .open = tracing_buffers_open, |
4612 | .read = tracing_buffers_read, | 4635 | .read = tracing_buffers_read, |
4636 | .poll = tracing_buffers_poll, | ||
4613 | .release = tracing_buffers_release, | 4637 | .release = tracing_buffers_release, |
4614 | .splice_read = tracing_buffers_splice_read, | 4638 | .splice_read = tracing_buffers_splice_read, |
4615 | .llseek = no_llseek, | 4639 | .llseek = no_llseek, |