diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index ce11fa50a2f0..1af4f8f2ab5d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -939,19 +939,20 @@ out: | |||
939 | return ret; | 939 | return ret; |
940 | } | 940 | } |
941 | 941 | ||
942 | /* TODO add a seq_buf_to_buffer() */ | ||
942 | static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt) | 943 | static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt) |
943 | { | 944 | { |
944 | int len; | 945 | int len; |
945 | 946 | ||
946 | if (s->len <= s->readpos) | 947 | if (trace_seq_used(s) <= s->seq.readpos) |
947 | return -EBUSY; | 948 | return -EBUSY; |
948 | 949 | ||
949 | len = s->len - s->readpos; | 950 | len = trace_seq_used(s) - s->seq.readpos; |
950 | if (cnt > len) | 951 | if (cnt > len) |
951 | cnt = len; | 952 | cnt = len; |
952 | memcpy(buf, s->buffer + s->readpos, cnt); | 953 | memcpy(buf, s->buffer + s->seq.readpos, cnt); |
953 | 954 | ||
954 | s->readpos += cnt; | 955 | s->seq.readpos += cnt; |
955 | return cnt; | 956 | return cnt; |
956 | } | 957 | } |
957 | 958 | ||
@@ -4313,6 +4314,8 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) | |||
4313 | goto out; | 4314 | goto out; |
4314 | } | 4315 | } |
4315 | 4316 | ||
4317 | trace_seq_init(&iter->seq); | ||
4318 | |||
4316 | /* | 4319 | /* |
4317 | * We make a copy of the current tracer to avoid concurrent | 4320 | * We make a copy of the current tracer to avoid concurrent |
4318 | * changes on it while we are reading. | 4321 | * changes on it while we are reading. |
@@ -4506,18 +4509,18 @@ waitagain: | |||
4506 | trace_access_lock(iter->cpu_file); | 4509 | trace_access_lock(iter->cpu_file); |
4507 | while (trace_find_next_entry_inc(iter) != NULL) { | 4510 | while (trace_find_next_entry_inc(iter) != NULL) { |
4508 | enum print_line_t ret; | 4511 | enum print_line_t ret; |
4509 | int len = iter->seq.len; | 4512 | int save_len = iter->seq.seq.len; |
4510 | 4513 | ||
4511 | ret = print_trace_line(iter); | 4514 | ret = print_trace_line(iter); |
4512 | if (ret == TRACE_TYPE_PARTIAL_LINE) { | 4515 | if (ret == TRACE_TYPE_PARTIAL_LINE) { |
4513 | /* don't print partial lines */ | 4516 | /* don't print partial lines */ |
4514 | iter->seq.len = len; | 4517 | iter->seq.seq.len = save_len; |
4515 | break; | 4518 | break; |
4516 | } | 4519 | } |
4517 | if (ret != TRACE_TYPE_NO_CONSUME) | 4520 | if (ret != TRACE_TYPE_NO_CONSUME) |
4518 | trace_consume(iter); | 4521 | trace_consume(iter); |
4519 | 4522 | ||
4520 | if (iter->seq.len >= cnt) | 4523 | if (trace_seq_used(&iter->seq) >= cnt) |
4521 | break; | 4524 | break; |
4522 | 4525 | ||
4523 | /* | 4526 | /* |
@@ -4533,7 +4536,7 @@ waitagain: | |||
4533 | 4536 | ||
4534 | /* Now copy what we have to the user */ | 4537 | /* Now copy what we have to the user */ |
4535 | sret = trace_seq_to_user(&iter->seq, ubuf, cnt); | 4538 | sret = trace_seq_to_user(&iter->seq, ubuf, cnt); |
4536 | if (iter->seq.readpos >= iter->seq.len) | 4539 | if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq)) |
4537 | trace_seq_init(&iter->seq); | 4540 | trace_seq_init(&iter->seq); |
4538 | 4541 | ||
4539 | /* | 4542 | /* |
@@ -4567,20 +4570,33 @@ static size_t | |||
4567 | tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter) | 4570 | tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter) |
4568 | { | 4571 | { |
4569 | size_t count; | 4572 | size_t count; |
4573 | int save_len; | ||
4570 | int ret; | 4574 | int ret; |
4571 | 4575 | ||
4572 | /* Seq buffer is page-sized, exactly what we need. */ | 4576 | /* Seq buffer is page-sized, exactly what we need. */ |
4573 | for (;;) { | 4577 | for (;;) { |
4574 | count = iter->seq.len; | 4578 | save_len = iter->seq.seq.len; |
4575 | ret = print_trace_line(iter); | 4579 | ret = print_trace_line(iter); |
4576 | count = iter->seq.len - count; | 4580 | |
4577 | if (rem < count) { | 4581 | if (trace_seq_has_overflowed(&iter->seq)) { |
4578 | rem = 0; | 4582 | iter->seq.seq.len = save_len; |
4579 | iter->seq.len -= count; | ||
4580 | break; | 4583 | break; |
4581 | } | 4584 | } |
4585 | |||
4586 | /* | ||
4587 | * This should not be hit, because it should only | ||
4588 | * be set if the iter->seq overflowed. But check it | ||
4589 | * anyway to be safe. | ||
4590 | */ | ||
4582 | if (ret == TRACE_TYPE_PARTIAL_LINE) { | 4591 | if (ret == TRACE_TYPE_PARTIAL_LINE) { |
4583 | iter->seq.len -= count; | 4592 | iter->seq.seq.len = save_len; |
4593 | break; | ||
4594 | } | ||
4595 | |||
4596 | count = trace_seq_used(&iter->seq) - save_len; | ||
4597 | if (rem < count) { | ||
4598 | rem = 0; | ||
4599 | iter->seq.seq.len = save_len; | ||
4584 | break; | 4600 | break; |
4585 | } | 4601 | } |
4586 | 4602 | ||
@@ -4661,13 +4677,13 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
4661 | /* Copy the data into the page, so we can start over. */ | 4677 | /* Copy the data into the page, so we can start over. */ |
4662 | ret = trace_seq_to_buffer(&iter->seq, | 4678 | ret = trace_seq_to_buffer(&iter->seq, |
4663 | page_address(spd.pages[i]), | 4679 | page_address(spd.pages[i]), |
4664 | iter->seq.len); | 4680 | trace_seq_used(&iter->seq)); |
4665 | if (ret < 0) { | 4681 | if (ret < 0) { |
4666 | __free_page(spd.pages[i]); | 4682 | __free_page(spd.pages[i]); |
4667 | break; | 4683 | break; |
4668 | } | 4684 | } |
4669 | spd.partial[i].offset = 0; | 4685 | spd.partial[i].offset = 0; |
4670 | spd.partial[i].len = iter->seq.len; | 4686 | spd.partial[i].len = trace_seq_used(&iter->seq); |
4671 | 4687 | ||
4672 | trace_seq_init(&iter->seq); | 4688 | trace_seq_init(&iter->seq); |
4673 | } | 4689 | } |
@@ -5667,7 +5683,8 @@ tracing_stats_read(struct file *filp, char __user *ubuf, | |||
5667 | cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu); | 5683 | cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu); |
5668 | trace_seq_printf(s, "read events: %ld\n", cnt); | 5684 | trace_seq_printf(s, "read events: %ld\n", cnt); |
5669 | 5685 | ||
5670 | count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len); | 5686 | count = simple_read_from_buffer(ubuf, count, ppos, |
5687 | s->buffer, trace_seq_used(s)); | ||
5671 | 5688 | ||
5672 | kfree(s); | 5689 | kfree(s); |
5673 | 5690 | ||
@@ -6630,11 +6647,19 @@ void | |||
6630 | trace_printk_seq(struct trace_seq *s) | 6647 | trace_printk_seq(struct trace_seq *s) |
6631 | { | 6648 | { |
6632 | /* Probably should print a warning here. */ | 6649 | /* Probably should print a warning here. */ |
6633 | if (s->len >= TRACE_MAX_PRINT) | 6650 | if (s->seq.len >= TRACE_MAX_PRINT) |
6634 | s->len = TRACE_MAX_PRINT; | 6651 | s->seq.len = TRACE_MAX_PRINT; |
6652 | |||
6653 | /* | ||
6654 | * More paranoid code. Although the buffer size is set to | ||
6655 | * PAGE_SIZE, and TRACE_MAX_PRINT is 1000, this is just | ||
6656 | * an extra layer of protection. | ||
6657 | */ | ||
6658 | if (WARN_ON_ONCE(s->seq.len >= s->seq.size)) | ||
6659 | s->seq.len = s->seq.size - 1; | ||
6635 | 6660 | ||
6636 | /* should be zero ended, but we are paranoid. */ | 6661 | /* should be zero ended, but we are paranoid. */ |
6637 | s->buffer[s->len] = 0; | 6662 | s->buffer[s->seq.len] = 0; |
6638 | 6663 | ||
6639 | printk(KERN_TRACE "%s", s->buffer); | 6664 | printk(KERN_TRACE "%s", s->buffer); |
6640 | 6665 | ||