nr_pages = PIPE_BUFFERS;
/*
- * Initiate read-ahead on this page range. however, don't call into
- * read-ahead if this is a non-zero offset (we are likely doing small
- * chunk splice and the page is already there) for a single page.
+ * Don't try to 2nd guess the read-ahead logic, call into
+ * page_cache_readahead() like the page cache reads would do.
*/
- if (!loff || nr_pages > 1)
- page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
+ page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
/*
* Now fill in the holes:
* If in nonblock mode then dont block on waiting
* for an in-flight io page
*/
- if (flags & SPLICE_F_NONBLOCK)
- break;
-
- lock_page(page);
+ if (flags & SPLICE_F_NONBLOCK) {
+ if (TestSetPageLocked(page))
+ break;
+ } else
+ lock_page(page);
/*
* page was truncated, stop here. if this isn't the
}
ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
- if (!ret) {
+ if (ret) {
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto find_page;
+ }
+ if (ret < 0)
+ goto out;
/*
- * Return the number of bytes written and mark page as
- * accessed, we are now done!
+ * Partial write has happened, so 'ret' already initialized by
+ * number of bytes written, Where is nothing we have to do here.
*/
+ } else
ret = this_len;
- mark_page_accessed(page);
- balance_dirty_pages_ratelimited(mapping);
- } else if (ret == AOP_TRUNCATED_PAGE) {
- page_cache_release(page);
- goto find_page;
- }
+ /*
+ * Return the number of bytes written and mark page as
+ * accessed, we are now done!
+ */
+ mark_page_accessed(page);
+ balance_dirty_pages_ratelimited(mapping);
out:
page_cache_release(page);
unlock_page(page);
* key here is the 'actor' worker passed in that actually moves the data
* to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
*/
-static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
- struct file *out, loff_t *ppos, size_t len,
- unsigned int flags, splice_actor *actor)
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
+ struct file *out, loff_t *ppos, size_t len,
+ unsigned int flags, splice_actor *actor)
{
int ret, do_wakeup, err;
struct splice_desc sd;
return ret;
}
+EXPORT_SYMBOL(__splice_from_pipe);
ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
loff_t *ppos, size_t len, unsigned int flags,