summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-04-19 15:56:12 +0200
committerJens Axboe <axboe@suse.de>2006-04-19 15:56:12 +0200
commitc4f895cbe1e95aab633207fb19c650b7c984c01a (patch)
tree3f8fa236d737da19bd9d7c38ab01079caf7d5f56 /fs
parent[PATCH] splice: close i_size truncate races on read (diff)
downloadlinux-c4f895cbe1e95aab633207fb19c650b7c984c01a.tar.xz
linux-c4f895cbe1e95aab633207fb19c650b7c984c01a.zip
[PATCH] splice: cleanup the SPLICE_F_NONBLOCK handling
- generic_file_splice_read() more readable and correct - Don't bail on page allocation with NONBLOCK set, just don't allow direct blocking on IO (eg lock_page). Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/splice.c30
1 files changed, 16 insertions, 14 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 7e8585574726..78cd264340f2 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -279,14 +279,6 @@ find_page:
page = find_get_page(mapping, index);
if (!page) {
/*
- * If in nonblock mode then dont block on
- * readpage (we've kicked readahead so there
- * will be asynchronous progress):
- */
- if (flags & SPLICE_F_NONBLOCK)
- break;
-
- /*
* page didn't exist, allocate one
*/
page = page_cache_alloc_cold(mapping);
@@ -307,6 +299,13 @@ find_page:
* If the page isn't uptodate, we may need to start io on it
*/
if (!PageUptodate(page)) {
+ /*
+ * If in nonblock mode then dont block on waiting
+ * for an in-flight io page
+ */
+ if (flags & SPLICE_F_NONBLOCK)
+ break;
+
lock_page(page);
/*
@@ -400,17 +399,20 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
while (len) {
ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
- if (ret <= 0)
+ if (ret < 0)
break;
+ else if (!ret) {
+ if (spliced)
+ break;
+ if (flags & SPLICE_F_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ }
*ppos += ret;
len -= ret;
spliced += ret;
-
- if (!(flags & SPLICE_F_NONBLOCK))
- continue;
- ret = -EAGAIN;
- break;
}
if (spliced)