@@ -2168,59 +2168,53 @@ static int lock_page_for_iocb(struct kiocb *iocb, struct page *page)
return lock_page_killable(page);
}
-static struct page *
-generic_file_buffered_read_readpage(struct kiocb *iocb,
- struct file *filp,
- struct address_space *mapping,
- struct page *page)
+static int filemap_readpage(struct kiocb *iocb, struct page *page)
{
- struct file_ra_state *ra = &filp->f_ra;
- int error;
+ struct file *file = iocb->ki_filp;
+ int error = -EAGAIN;
if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT)) {
unlock_page(page);
- put_page(page);
- return ERR_PTR(-EAGAIN);
+ goto out_put_page;
}
/*
- * A previous I/O error may have been due to temporary
- * failures, eg. multipath errors.
- * PG_error will be set again if readpage fails.
+ * A previous I/O error may have been due to temporary failures, e.g.
+ * multipath errors. PG_error will be set again if readpage fails.
*/
ClearPageError(page);
/* Start the actual read. The read will unlock the page. */
- error = mapping->a_ops->readpage(filp, page);
-
- if (unlikely(error)) {
- put_page(page);
- return error != AOP_TRUNCATED_PAGE ? ERR_PTR(error) : NULL;
- }
+ error = file->f_mapping->a_ops->readpage(file, page);
+ if (unlikely(error))
+ goto out_put_page;
if (!PageUptodate(page)) {
error = lock_page_for_iocb(iocb, page);
- if (unlikely(error)) {
- put_page(page);
- return ERR_PTR(error);
- }
+ if (unlikely(error))
+ goto out_put_page;
+
if (!PageUptodate(page)) {
if (page->mapping == NULL) {
/*
* invalidate_mapping_pages got it
*/
unlock_page(page);
- put_page(page);
- return NULL;
+ error = AOP_TRUNCATED_PAGE;
+ goto out_put_page;
}
unlock_page(page);
- shrink_readahead_size_eio(ra);
- put_page(page);
- return ERR_PTR(-EIO);
+ shrink_readahead_size_eio(&file->f_ra);
+ error = -EIO;
+ goto out_put_page;
}
+
unlock_page(page);
}
+ return 0;
- return page;
+out_put_page:
+ put_page(page);
+ return error;
}
static struct page *
@@ -2291,7 +2285,13 @@ generic_file_buffered_read_pagenotuptodate(struct kiocb *iocb,
return page;
}
- return generic_file_buffered_read_readpage(iocb, filp, mapping, page);
+ error = filemap_readpage(iocb, page);
+ if (error) {
+ if (error == AOP_TRUNCATED_PAGE)
+ return NULL;
+ return ERR_PTR(error);
+ }
+ return page;
}
static struct page *
@@ -2322,7 +2322,13 @@ generic_file_buffered_read_no_cached_page(struct kiocb *iocb,
return error != -EEXIST ? ERR_PTR(error) : NULL;
}
- return generic_file_buffered_read_readpage(iocb, filp, mapping, page);
+ error = filemap_readpage(iocb, page);
+ if (error) {
+ if (error == AOP_TRUNCATED_PAGE)
+ return NULL;
+ return ERR_PTR(error);
+ }
+ return page;
}
static int generic_file_buffered_read_get_pages(struct kiocb *iocb,
Stop passing pointless arguments, and return an int instead of a page struct that contains either the passed in page, an ERR_PTR or NULL and use goto labels to share common code. Also rename the function to filemap_readpage as it is a fairly generic wrapper around ->readpage that isn't really specific to generic_file_buffered_read. Signed-off-by: Christoph Hellwig <hch@lst.de> --- mm/filemap.c | 66 ++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 30 deletions(-)