Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −25
Original line number Diff line number Diff line
@@ -370,8 +370,10 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
			 * for an in-flight io page
			 */
			if (flags & SPLICE_F_NONBLOCK) {
				if (TestSetPageLocked(page))
				if (TestSetPageLocked(page)) {
					error = -EAGAIN;
					break;
				}
			} else
				lock_page(page);

@@ -479,9 +481,8 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
				 struct pipe_inode_info *pipe, size_t len,
				 unsigned int flags)
{
	ssize_t spliced;
	int ret;
	loff_t isize, left;
	int ret;

	isize = i_size_read(in->f_mapping->host);
	if (unlikely(*ppos >= isize))
@@ -491,29 +492,9 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
	if (unlikely(left < len))
		len = left;

	ret = 0;
	spliced = 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;
			}
		}

	if (ret > 0)
		*ppos += ret;
		len -= ret;
		spliced += ret;
	}

	if (spliced)
		return spliced;

	return ret;
}