diff options
author | Jens Axboe <axboe@suse.de> | 2006-04-19 15:56:12 +0200 |
---|---|---|
committer | Jens Axboe <axboe@suse.de> | 2006-04-19 15:56:12 +0200 |
commit | c4f895cbe1e95aab633207fb19c650b7c984c01a (patch) | |
tree | 3f8fa236d737da19bd9d7c38ab01079caf7d5f56 /fs | |
parent | [PATCH] splice: close i_size truncate races on read (diff) | |
download | linux-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.c | 30 |
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) |