From bcd4f3acbaec102e2b8000c977ecc38dcd0fe367 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 Jul 2007 14:41:49 +0200 Subject: splice: direct splicing updates ppos twice OGAWA Hirofumi reported that he's noticed nfsd read corruption in recent kernels, and did the hard work of discovering that it's due to splice updating the file position twice. This means that the next operation would start further ahead than it should. nfsd_vfs_read() splice_direct_to_actor() while(len) { do_splice_to() [update sd->pos] -> generic_file_splice_read() [read from sd->pos] nfsd_direct_splice_actor() -> __splice_from_pipe() [update sd->pos] There's nothing wrong with the core splice code, but the direct splicing is an addon that calls both input and output paths. So it has to take care in locally caching offset so it remains correct. Signed-off-by: Jens Axboe --- fs/splice.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/splice.c b/fs/splice.c index 6c9828651e6..53fc2082a46 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1061,8 +1061,9 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, while (len) { size_t read_len; + loff_t pos = sd->pos; - ret = do_splice_to(in, &sd->pos, pipe, len, flags); + ret = do_splice_to(in, &pos, pipe, len, flags); if (unlikely(ret <= 0)) goto out_release; @@ -1080,6 +1081,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, bytes += ret; len -= ret; + sd->pos = pos; if (ret < read_len) goto out_release; -- cgit v1.2.3