Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tracing: fix splice return too large

I got these from strace:

splice(0x3, 0, 0x5, 0, 0x1000, 0x1) = 12288
splice(0x3, 0, 0x5, 0, 0x1000, 0x1) = 12288
splice(0x3, 0, 0x5, 0, 0x1000, 0x1) = 12288
splice(0x3, 0, 0x5, 0, 0x1000, 0x1) = 16384
splice(0x3, 0, 0x5, 0, 0x1000, 0x1) = 8192
splice(0x3, 0, 0x5, 0, 0x1000, 0x1) = 8192
splice(0x3, 0, 0x5, 0, 0x1000, 0x1) = 8192

I wanted to splice_read 4096 bytes, but it returns 8192 or larger.

It is because the return value of tracing_buffers_splice_read()
does not include "zero out any left over data" bytes.

But tracing_buffers_read() includes these bytes, we make them
consistent.

Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <srostedt@redhat.com>
LKML-Reference: <49D46674.9030804@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Lai Jiangshan and committed by
Ingo Molnar
93cfb3c9 c7625a55

+14 -2
+14 -2
kernel/trace/trace.c
··· 3428 3428 int size, i; 3429 3429 size_t ret; 3430 3430 3431 - for (i = 0; i < PIPE_BUFFERS && len; i++, len -= size) { 3431 + if (*ppos & (PAGE_SIZE - 1)) { 3432 + WARN_ONCE(1, "Ftrace: previous read must page-align\n"); 3433 + return -EINVAL; 3434 + } 3435 + 3436 + if (len & (PAGE_SIZE - 1)) { 3437 + WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); 3438 + if (len < PAGE_SIZE) 3439 + return -EINVAL; 3440 + len &= PAGE_MASK; 3441 + } 3442 + 3443 + for (i = 0; i < PIPE_BUFFERS && len; i++, len -= PAGE_SIZE) { 3432 3444 struct page *page; 3433 3445 int r; 3434 3446 ··· 3479 3467 spd.partial[i].offset = 0; 3480 3468 spd.partial[i].private = (unsigned long)ref; 3481 3469 spd.nr_pages++; 3482 - *ppos += size; 3470 + *ppos += PAGE_SIZE; 3483 3471 } 3484 3472 3485 3473 spd.nr_pages = i;