aboutsummaryrefslogtreecommitdiff
path: root/mm/filemap.c
diff options
context:
space:
mode:
authorMatthew Wilcox (Oracle)2021-02-24 12:02:15 -0800
committerLinus Torvalds2021-02-24 13:38:28 -0800
commit68430303c84e1fd457a05f424b02ea8393708552 (patch)
tree234b569605da408e35671b19a2f2348028403842 /mm/filemap.c
parent33a0f5c6b34f58e632f1855ff29228d49bc23bcc (diff)
mm/filemap: change filemap_read_page calling conventions
Make this function more generic by passing the file instead of the iocb. Check in the callers whether we should call readpage or not. Also make it return an errno / 0 / AOP_TRUNCATED_PAGE, and make calling put_page() the caller's responsibility. Link: https://lkml.kernel.org/r/20210122160140.223228-10-willy@infradead.org Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Kent Overstreet <kent.overstreet@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Cc: Miaohe Lin <linmiaohe@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c89
1 files changed, 42 insertions, 47 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 8bd1bb375d07..0b7310971678 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2199,56 +2199,38 @@ retry:
rcu_read_unlock();
}
-static struct page *filemap_read_page(struct kiocb *iocb, struct file *filp,
- struct address_space *mapping, struct page *page)
+static int filemap_read_page(struct file *file, struct address_space *mapping,
+ struct page *page)
{
- struct file_ra_state *ra = &filp->f_ra;
int error;
- if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ)) {
- unlock_page(page);
- put_page(page);
- return ERR_PTR(-EAGAIN);
- }
-
/*
- * 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,
+ * eg. 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 = mapping->a_ops->readpage(file, page);
+ if (error)
+ return error;
+ if (PageUptodate(page))
+ return 0;
+ error = lock_page_killable(page);
+ if (error)
+ return error;
if (!PageUptodate(page)) {
- error = lock_page_killable(page);
- if (unlikely(error)) {
- put_page(page);
- return ERR_PTR(error);
- }
- if (!PageUptodate(page)) {
- if (page->mapping == NULL) {
- /*
- * invalidate_mapping_pages got it
- */
- unlock_page(page);
- put_page(page);
- return NULL;
- }
- unlock_page(page);
- shrink_readahead_size_eio(ra);
- put_page(page);
- return ERR_PTR(-EIO);
+ if (page->mapping == NULL) {
+ /* page truncated */
+ error = AOP_TRUNCATED_PAGE;
+ } else {
+ shrink_readahead_size_eio(&file->f_ra);
+ error = -EIO;
}
- unlock_page(page);
}
-
- return page;
+ unlock_page(page);
+ return error;
}
static struct page *filemap_update_page(struct kiocb *iocb, struct file *filp,
@@ -2290,7 +2272,18 @@ uptodate:
return page;
readpage:
- return filemap_read_page(iocb, filp, mapping, page);
+ if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ)) {
+ unlock_page(page);
+ put_page(page);
+ return ERR_PTR(-EAGAIN);
+ }
+ error = filemap_read_page(iocb->ki_filp, mapping, page);
+ if (!error)
+ return page;
+ put_page(page);
+ if (error == AOP_TRUNCATED_PAGE)
+ return NULL;
+ return ERR_PTR(error);
truncated:
unlock_page(page);
put_page(page);
@@ -2306,7 +2299,7 @@ static struct page *filemap_create_page(struct kiocb *iocb,
struct page *page;
int error;
- if (iocb->ki_flags & IOCB_NOIO)
+ if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ))
return ERR_PTR(-EAGAIN);
page = page_cache_alloc(mapping);
@@ -2315,12 +2308,14 @@ static struct page *filemap_create_page(struct kiocb *iocb,
error = add_to_page_cache_lru(page, mapping, index,
mapping_gfp_constraint(mapping, GFP_KERNEL));
- if (error) {
- put_page(page);
- return error != -EEXIST ? ERR_PTR(error) : NULL;
- }
-
- return filemap_read_page(iocb, filp, mapping, page);
+ if (!error)
+ error = filemap_read_page(iocb->ki_filp, mapping, page);
+ if (!error)
+ return page;
+ put_page(page);
+ if (error == -EEXIST || error == AOP_TRUNCATED_PAGE)
+ return NULL;
+ return ERR_PTR(error);
}
static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter,