diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-11-30 10:48:24 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-11-30 10:48:24 -0800 |
commit | f112a2fd1f5999c6029551f901952392d900cf99 (patch) | |
tree | b9ee2d8856de063af2079236e92549b2078e6746 | |
parent | 3b266a52d8d6e02ea6c1bb52c96342128e624554 (diff) | |
parent | 3253d9d093376d62b4a56e609f15d2ec5085ac73 (diff) | |
download | linux-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
-rw-r--r-- | fs/splice.c | 14 |
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); |