summaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-11-30 10:48:24 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2019-11-30 10:48:24 -0800
commitf112a2fd1f5999c6029551f901952392d900cf99 (patch)
treeb9ee2d8856de063af2079236e92549b2078e6746 /fs/splice.c
parent3b266a52d8d6e02ea6c1bb52c96342128e624554 (diff)
parent3253d9d093376d62b4a56e609f15d2ec5085ac73 (diff)
downloadlinux-f112a2fd1f5999c6029551f901952392d900cf99.tar.bz2
Merge tag 'vfs-5.5-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull splice fix from Darrick Wong: "Fix another place in the splice code where a pipe could ask a filesystem for a longer read than the pipe actually has free buffer space" * tag 'vfs-5.5-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: splice: only read in as much information as there is pipe buffer space
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 98412721f056..e509239d7e06 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -945,12 +945,13 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
WARN_ON_ONCE(pipe->nrbufs != 0);
while (len) {
+ unsigned int pipe_pages;
size_t read_len;
loff_t pos = sd->pos, prev_pos = pos;
/* Don't try to read more the pipe has space for. */
- read_len = min_t(size_t, len,
- (pipe->buffers - pipe->nrbufs) << PAGE_SHIFT);
+ pipe_pages = pipe->buffers - pipe->nrbufs;
+ read_len = min(len, (size_t)pipe_pages << PAGE_SHIFT);
ret = do_splice_to(in, &pos, pipe, read_len, flags);
if (unlikely(ret <= 0))
goto out_release;
@@ -1180,8 +1181,15 @@ static long do_splice(struct file *in, loff_t __user *off_in,
pipe_lock(opipe);
ret = wait_for_space(opipe, flags);
- if (!ret)
+ if (!ret) {
+ unsigned int pipe_pages;
+
+ /* Don't try to read more the pipe has space for. */
+ pipe_pages = opipe->buffers - opipe->nrbufs;
+ len = min(len, (size_t)pipe_pages << PAGE_SHIFT);
+
ret = do_splice_to(in, &offset, opipe, len, flags);
+ }
pipe_unlock(opipe);
if (ret > 0)
wakeup_pipe_readers(opipe);