Commit 8191ecd1 authored by Jens Axboe's avatar Jens Axboe

splice: fix infinite loop in generic_file_splice_read()

There's a quirky loop in generic_file_splice_read() that could go
on indefinitely, if the file splice returns 0 permanently (and not
just as a temporary condition). Get rid of the loop and pass
back -EAGAIN correctly from __generic_file_splice_read(), so we
handle that condition properly as well.
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent f4be31ec
...@@ -370,8 +370,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, ...@@ -370,8 +370,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
* for an in-flight io page * for an in-flight io page
*/ */
if (flags & SPLICE_F_NONBLOCK) { if (flags & SPLICE_F_NONBLOCK) {
if (TestSetPageLocked(page)) if (TestSetPageLocked(page)) {
error = -EAGAIN;
break; break;
}
} else } else
lock_page(page); lock_page(page);
...@@ -479,9 +481,8 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, ...@@ -479,9 +481,8 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len, struct pipe_inode_info *pipe, size_t len,
unsigned int flags) unsigned int flags)
{ {
ssize_t spliced;
int ret;
loff_t isize, left; loff_t isize, left;
int ret;
isize = i_size_read(in->f_mapping->host); isize = i_size_read(in->f_mapping->host);
if (unlikely(*ppos >= isize)) if (unlikely(*ppos >= isize))
...@@ -491,29 +492,9 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, ...@@ -491,29 +492,9 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
if (unlikely(left < len)) if (unlikely(left < len))
len = left; len = left;
ret = 0; ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
spliced = 0; if (ret > 0)
while (len && !spliced) {
ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
if (ret < 0)
break;
else if (!ret) {
if (spliced)
break;
if (flags & SPLICE_F_NONBLOCK) {
ret = -EAGAIN;
break;
}
}
*ppos += ret; *ppos += ret;
len -= ret;
spliced += ret;
}
if (spliced)
return spliced;
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment