aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbhi Das <adas@redhat.com>2016-11-16 22:44:23 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2016-11-17 00:00:48 -0500
commit680bb946a1ae04fe0ff369a4965f76b48c07dc54 (patch)
treebe2ca455a6186b86a08e3ab1c22d49748cc6ed75
parent4a59015372840a6fc35d7fd40638a9d5dc3ec958 (diff)
fix iov_iter_advance() for ITER_PIPE
iov_iter_advance() needs to decrement iter->count by the number of bytes we'd moved beyond. Normal flavours do that, but ITER_PIPE doesn't and ITER_PIPE generic_file_read_iter() for O_DIRECT files ends up with a bogus fallback to page cache read, resulting in incorrect values for file offset and bytes read. Signed-off-by: Abhi Das <adas@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--lib/iov_iter.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index f0c7f1481bae..f2bd21b93dfc 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -683,10 +683,11 @@ static void pipe_advance(struct iov_iter *i, size_t size)
683 struct pipe_inode_info *pipe = i->pipe; 683 struct pipe_inode_info *pipe = i->pipe;
684 struct pipe_buffer *buf; 684 struct pipe_buffer *buf;
685 int idx = i->idx; 685 int idx = i->idx;
686 size_t off = i->iov_offset; 686 size_t off = i->iov_offset, orig_sz;
687 687
688 if (unlikely(i->count < size)) 688 if (unlikely(i->count < size))
689 size = i->count; 689 size = i->count;
690 orig_sz = size;
690 691
691 if (size) { 692 if (size) {
692 if (off) /* make it relative to the beginning of buffer */ 693 if (off) /* make it relative to the beginning of buffer */
@@ -713,6 +714,7 @@ static void pipe_advance(struct iov_iter *i, size_t size)
713 pipe->nrbufs--; 714 pipe->nrbufs--;
714 } 715 }
715 } 716 }
717 i->count -= orig_sz;
716} 718}
717 719
718void iov_iter_advance(struct iov_iter *i, size_t size) 720void iov_iter_advance(struct iov_iter *i, size_t size)