Patchwork [Hardy,1/1] splice: fix infinite loop in generic_file_splice_read()

login
register
mail settings
Submitter Leann Ogasawara
Date Aug. 23, 2011, 7:27 p.m.
Message ID <1314127653.2020.14.camel@adamo>
Download mbox | patch
Permalink /patch/111172/
State New
Headers show

Comments

Leann Ogasawara - Aug. 23, 2011, 7:27 p.m.
BugLink: http://bugs.launchpad.net/bugs/790557

SRU Justification:

Impact: Without the fix, users can experience "sporadic kernel lockups
on a Ubuntu Hardy LTS fileserver which produces serious downtimes."

Fix: upstream commit 8191ecd1d14c6914c660dfa007154860a7908857

User has built their own Hardy kernel with the above patch applied.
They can confirm they no longer experience the sporadic lockups on their
production system.  This is a clean cherry-pick from upstream.  Please
consider for Hardy SRU.

Thanks,
Leann

From 8cd7c215bccee7dcd8b8d70fa335657013a65df1 Mon Sep 17 00:00:00 2001
From: Jens Axboe <jens.axboe@oracle.com>
Date: Thu, 10 Apr 2008 08:24:25 +0200
Subject: [PATCH] splice: fix infinite loop in generic_file_splice_read()

BugLink: http://bugs.launchpad.net/bugs/790557

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: Jens Axboe <jens.axboe@oracle.com>
(cherry picked from commit 8191ecd1d14c6914c660dfa007154860a7908857)

Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
---
 fs/splice.c |   31 ++++++-------------------------
 1 files changed, 6 insertions(+), 25 deletions(-)
Tim Gardner - Aug. 23, 2011, 7:33 p.m.
Clean cherry-pick with good test results.

Patch

diff --git a/fs/splice.c b/fs/splice.c
index ef9fc8f..b2872d7 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -364,8 +364,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);
 
@@ -473,9 +475,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))
@@ -485,29 +486,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;
-			}
-		}
-
+	ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
+	if (ret > 0)
 		*ppos += ret;
-		len -= ret;
-		spliced += ret;
-	}
-
-	if (spliced)
-		return spliced;
 
 	return ret;
 }