aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <srostedt@redhat.com>2013-03-05 16:18:16 -0500
committerSteven Rostedt <rostedt@goodmis.org>2013-03-15 00:35:47 -0400
commit6de58e6269cd0568ca5fbae14423914eff0f7811 (patch)
tree3ce4d96d1549925a2724ed713d76cf2f9683ff72 /kernel/trace
parent0b85ffc293044393623059eda9904a7d5b644e36 (diff)
tracing: Add snapshot_raw to extract the raw data from snapshot
Add a 'snapshot_raw' per_cpu file that allows tools to read the raw binary data of the snapshot buffer. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace.c113
1 files changed, 95 insertions, 18 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 303932688964..9bb0b52cbd32 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4206,6 +4206,12 @@ static int tracing_clock_open(struct inode *inode, struct file *file)
4206 return single_open(file, tracing_clock_show, inode->i_private); 4206 return single_open(file, tracing_clock_show, inode->i_private);
4207} 4207}
4208 4208
4209struct ftrace_buffer_info {
4210 struct trace_iterator iter;
4211 void *spare;
4212 unsigned int read;
4213};
4214
4209#ifdef CONFIG_TRACER_SNAPSHOT 4215#ifdef CONFIG_TRACER_SNAPSHOT
4210static int tracing_snapshot_open(struct inode *inode, struct file *file) 4216static int tracing_snapshot_open(struct inode *inode, struct file *file)
4211{ 4217{
@@ -4336,6 +4342,35 @@ static int tracing_snapshot_release(struct inode *inode, struct file *file)
4336 return 0; 4342 return 0;
4337} 4343}
4338 4344
4345static int tracing_buffers_open(struct inode *inode, struct file *filp);
4346static ssize_t tracing_buffers_read(struct file *filp, char __user *ubuf,
4347 size_t count, loff_t *ppos);
4348static int tracing_buffers_release(struct inode *inode, struct file *file);
4349static ssize_t tracing_buffers_splice_read(struct file *file, loff_t *ppos,
4350 struct pipe_inode_info *pipe, size_t len, unsigned int flags);
4351
4352static int snapshot_raw_open(struct inode *inode, struct file *filp)
4353{
4354 struct ftrace_buffer_info *info;
4355 int ret;
4356
4357 ret = tracing_buffers_open(inode, filp);
4358 if (ret < 0)
4359 return ret;
4360
4361 info = filp->private_data;
4362
4363 if (info->iter.trace->use_max_tr) {
4364 tracing_buffers_release(inode, filp);
4365 return -EBUSY;
4366 }
4367
4368 info->iter.snapshot = true;
4369 info->iter.trace_buffer = &info->iter.tr->max_buffer;
4370
4371 return ret;
4372}
4373
4339#endif /* CONFIG_TRACER_SNAPSHOT */ 4374#endif /* CONFIG_TRACER_SNAPSHOT */
4340 4375
4341 4376
@@ -4402,14 +4437,17 @@ static const struct file_operations snapshot_fops = {
4402 .llseek = tracing_seek, 4437 .llseek = tracing_seek,
4403 .release = tracing_snapshot_release, 4438 .release = tracing_snapshot_release,
4404}; 4439};
4405#endif /* CONFIG_TRACER_SNAPSHOT */
4406 4440
4407struct ftrace_buffer_info { 4441static const struct file_operations snapshot_raw_fops = {
4408 struct trace_iterator iter; 4442 .open = snapshot_raw_open,
4409 void *spare; 4443 .read = tracing_buffers_read,
4410 unsigned int read; 4444 .release = tracing_buffers_release,
4445 .splice_read = tracing_buffers_splice_read,
4446 .llseek = no_llseek,
4411}; 4447};
4412 4448
4449#endif /* CONFIG_TRACER_SNAPSHOT */
4450
4413static int tracing_buffers_open(struct inode *inode, struct file *filp) 4451static int tracing_buffers_open(struct inode *inode, struct file *filp)
4414{ 4452{
4415 struct trace_cpu *tc = inode->i_private; 4453 struct trace_cpu *tc = inode->i_private;
@@ -4452,16 +4490,26 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
4452 struct ftrace_buffer_info *info = filp->private_data; 4490 struct ftrace_buffer_info *info = filp->private_data;
4453 struct trace_iterator *iter = &info->iter; 4491 struct trace_iterator *iter = &info->iter;
4454 ssize_t ret; 4492 ssize_t ret;
4455 size_t size; 4493 ssize_t size;
4456 4494
4457 if (!count) 4495 if (!count)
4458 return 0; 4496 return 0;
4459 4497
4498 mutex_lock(&trace_types_lock);
4499
4500#ifdef CONFIG_TRACER_MAX_TRACE
4501 if (iter->snapshot && iter->tr->current_trace->use_max_tr) {
4502 size = -EBUSY;
4503 goto out_unlock;
4504 }
4505#endif
4506
4460 if (!info->spare) 4507 if (!info->spare)
4461 info->spare = ring_buffer_alloc_read_page(iter->trace_buffer->buffer, 4508 info->spare = ring_buffer_alloc_read_page(iter->trace_buffer->buffer,
4462 iter->cpu_file); 4509 iter->cpu_file);
4510 size = -ENOMEM;
4463 if (!info->spare) 4511 if (!info->spare)
4464 return -ENOMEM; 4512 goto out_unlock;
4465 4513
4466 /* Do we have previous read data to read? */ 4514 /* Do we have previous read data to read? */
4467 if (info->read < PAGE_SIZE) 4515 if (info->read < PAGE_SIZE)
@@ -4477,31 +4525,42 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
4477 4525
4478 if (ret < 0) { 4526 if (ret < 0) {
4479 if (trace_empty(iter)) { 4527 if (trace_empty(iter)) {
4480 if ((filp->f_flags & O_NONBLOCK)) 4528 if ((filp->f_flags & O_NONBLOCK)) {
4481 return -EAGAIN; 4529 size = -EAGAIN;
4530 goto out_unlock;
4531 }
4532 mutex_unlock(&trace_types_lock);
4482 iter->trace->wait_pipe(iter); 4533 iter->trace->wait_pipe(iter);
4483 if (signal_pending(current)) 4534 mutex_lock(&trace_types_lock);
4484 return -EINTR; 4535 if (signal_pending(current)) {
4536 size = -EINTR;
4537 goto out_unlock;
4538 }
4485 goto again; 4539 goto again;
4486 } 4540 }
4487 return 0; 4541 size = 0;
4542 goto out_unlock;
4488 } 4543 }
4489 4544
4490 info->read = 0; 4545 info->read = 0;
4491
4492 read: 4546 read:
4493 size = PAGE_SIZE - info->read; 4547 size = PAGE_SIZE - info->read;
4494 if (size > count) 4548 if (size > count)
4495 size = count; 4549 size = count;
4496 4550
4497 ret = copy_to_user(ubuf, info->spare + info->read, size); 4551 ret = copy_to_user(ubuf, info->spare + info->read, size);
4498 if (ret == size) 4552 if (ret == size) {
4499 return -EFAULT; 4553 size = -EFAULT;
4554 goto out_unlock;
4555 }
4500 size -= ret; 4556 size -= ret;
4501 4557
4502 *ppos += size; 4558 *ppos += size;
4503 info->read += size; 4559 info->read += size;
4504 4560
4561 out_unlock:
4562 mutex_unlock(&trace_types_lock);
4563
4505 return size; 4564 return size;
4506} 4565}
4507 4566
@@ -4591,10 +4650,21 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
4591 }; 4650 };
4592 struct buffer_ref *ref; 4651 struct buffer_ref *ref;
4593 int entries, size, i; 4652 int entries, size, i;
4594 size_t ret; 4653 ssize_t ret;
4595 4654
4596 if (splice_grow_spd(pipe, &spd)) 4655 mutex_lock(&trace_types_lock);
4597 return -ENOMEM; 4656
4657#ifdef CONFIG_TRACER_MAX_TRACE
4658 if (iter->snapshot && iter->tr->current_trace->use_max_tr) {
4659 ret = -EBUSY;
4660 goto out;
4661 }
4662#endif
4663
4664 if (splice_grow_spd(pipe, &spd)) {
4665 ret = -ENOMEM;
4666 goto out;
4667 }
4598 4668
4599 if (*ppos & (PAGE_SIZE - 1)) { 4669 if (*ppos & (PAGE_SIZE - 1)) {
4600 ret = -EINVAL; 4670 ret = -EINVAL;
@@ -4666,7 +4736,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
4666 ret = -EAGAIN; 4736 ret = -EAGAIN;
4667 goto out; 4737 goto out;
4668 } 4738 }
4739 mutex_unlock(&trace_types_lock);
4669 iter->trace->wait_pipe(iter); 4740 iter->trace->wait_pipe(iter);
4741 mutex_lock(&trace_types_lock);
4670 if (signal_pending(current)) { 4742 if (signal_pending(current)) {
4671 ret = -EINTR; 4743 ret = -EINTR;
4672 goto out; 4744 goto out;
@@ -4677,6 +4749,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
4677 ret = splice_to_pipe(pipe, &spd); 4749 ret = splice_to_pipe(pipe, &spd);
4678 splice_shrink_spd(&spd); 4750 splice_shrink_spd(&spd);
4679out: 4751out:
4752 mutex_unlock(&trace_types_lock);
4753
4680 return ret; 4754 return ret;
4681} 4755}
4682 4756
@@ -4880,6 +4954,9 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
4880#ifdef CONFIG_TRACER_SNAPSHOT 4954#ifdef CONFIG_TRACER_SNAPSHOT
4881 trace_create_file("snapshot", 0644, d_cpu, 4955 trace_create_file("snapshot", 0644, d_cpu,
4882 (void *)&data->trace_cpu, &snapshot_fops); 4956 (void *)&data->trace_cpu, &snapshot_fops);
4957
4958 trace_create_file("snapshot_raw", 0444, d_cpu,
4959 (void *)&data->trace_cpu, &snapshot_raw_fops);
4883#endif 4960#endif
4884} 4961}
4885 4962