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>
This commit is contained in:
parent
33a0f5c6b3
commit
68430303c8
89
mm/filemap.c
89
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 (page->mapping == NULL) {
|
||||
/* page truncated */
|
||||
error = AOP_TRUNCATED_PAGE;
|
||||
} else {
|
||||
shrink_readahead_size_eio(&file->f_ra);
|
||||
error = -EIO;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue