Commit 68430303 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Linus Torvalds

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.orgSigned-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 33a0f5c6
...@@ -2199,56 +2199,38 @@ static void filemap_get_read_batch(struct address_space *mapping, ...@@ -2199,56 +2199,38 @@ static void filemap_get_read_batch(struct address_space *mapping,
rcu_read_unlock(); rcu_read_unlock();
} }
static struct page *filemap_read_page(struct kiocb *iocb, struct file *filp, static int filemap_read_page(struct file *file, struct address_space *mapping,
struct address_space *mapping, struct page *page) struct page *page)
{ {
struct file_ra_state *ra = &filp->f_ra;
int error; 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 * A previous I/O error may have been due to temporary failures,
* failures, eg. multipath errors. * eg. multipath errors. PG_error will be set again if readpage
* PG_error will be set again if readpage fails. * fails.
*/ */
ClearPageError(page); ClearPageError(page);
/* Start the actual read. The read will unlock the page. */ /* Start the actual read. The read will unlock the page. */
error = mapping->a_ops->readpage(filp, page); error = mapping->a_ops->readpage(file, page);
if (error)
if (unlikely(error)) { return error;
put_page(page); if (PageUptodate(page))
return error != AOP_TRUNCATED_PAGE ? ERR_PTR(error) : NULL; return 0;
}
error = lock_page_killable(page);
if (error)
return error;
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
error = lock_page_killable(page); if (page->mapping == NULL) {
if (unlikely(error)) { /* page truncated */
put_page(page); error = AOP_TRUNCATED_PAGE;
return ERR_PTR(error); } else {
} shrink_readahead_size_eio(&file->f_ra);
if (!PageUptodate(page)) { error = -EIO;
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);
} }
unlock_page(page);
} }
unlock_page(page);
return page; return error;
} }
static struct page *filemap_update_page(struct kiocb *iocb, struct file *filp, static struct page *filemap_update_page(struct kiocb *iocb, struct file *filp,
...@@ -2290,7 +2272,18 @@ static struct page *filemap_update_page(struct kiocb *iocb, struct file *filp, ...@@ -2290,7 +2272,18 @@ static struct page *filemap_update_page(struct kiocb *iocb, struct file *filp,
return page; return page;
readpage: 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: truncated:
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);
...@@ -2306,7 +2299,7 @@ static struct page *filemap_create_page(struct kiocb *iocb, ...@@ -2306,7 +2299,7 @@ static struct page *filemap_create_page(struct kiocb *iocb,
struct page *page; struct page *page;
int error; int error;
if (iocb->ki_flags & IOCB_NOIO) if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ))
return ERR_PTR(-EAGAIN); return ERR_PTR(-EAGAIN);
page = page_cache_alloc(mapping); page = page_cache_alloc(mapping);
...@@ -2315,12 +2308,14 @@ static struct page *filemap_create_page(struct kiocb *iocb, ...@@ -2315,12 +2308,14 @@ static struct page *filemap_create_page(struct kiocb *iocb,
error = add_to_page_cache_lru(page, mapping, index, error = add_to_page_cache_lru(page, mapping, index,
mapping_gfp_constraint(mapping, GFP_KERNEL)); mapping_gfp_constraint(mapping, GFP_KERNEL));
if (error) { if (!error)
put_page(page); error = filemap_read_page(iocb->ki_filp, mapping, page);
return error != -EEXIST ? ERR_PTR(error) : NULL; if (!error)
} return page;
put_page(page);
return filemap_read_page(iocb, filp, mapping, 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, static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment