Return an errno and add a new by reference argument for the allocated page, which allows to cleanup the error unwindining in the function and the caller. Also rename the function to filemap_new_page which is both shorter and more descriptive. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- mm/filemap.c | 53 ++++++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 5cdf8090d4e12c..9e1cc18afe1134 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2300,41 +2300,27 @@ static int filemap_make_page_uptodate(struct kiocb *iocb, struct iov_iter *iter, return error; } -static struct page * -generic_file_buffered_read_no_cached_page(struct kiocb *iocb, - struct iov_iter *iter) +static int filemap_new_page(struct kiocb *iocb, struct iov_iter *iter, + struct page **page) { - struct file *filp = iocb->ki_filp; - struct address_space *mapping = filp->f_mapping; + struct address_space *mapping = iocb->ki_filp->f_mapping; + gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); pgoff_t index = iocb->ki_pos >> PAGE_SHIFT; - struct page *page; int error; if (iocb->ki_flags & IOCB_NOIO) - return ERR_PTR(-EAGAIN); + return -EAGAIN; - /* - * Ok, it wasn't cached, so we need to create a new - * page.. - */ - page = page_cache_alloc(mapping); + *page = page_cache_alloc(mapping); if (!page) - return ERR_PTR(-ENOMEM); - - error = add_to_page_cache_lru(page, mapping, index, - mapping_gfp_constraint(mapping, GFP_KERNEL)); + return -ENOMEM; + error = add_to_page_cache_lru(*page, mapping, index, gfp); if (error) { - put_page(page); - return error != -EEXIST ? ERR_PTR(error) : NULL; + put_page(*page); + return error; } - error = filemap_readpage(iocb, page); - if (error) { - if (error == AOP_TRUNCATED_PAGE) - return NULL; - return ERR_PTR(error); - } - return page; + return filemap_readpage(iocb, *page); } static int generic_file_buffered_read_get_pages(struct kiocb *iocb, @@ -2366,18 +2352,14 @@ static int generic_file_buffered_read_get_pages(struct kiocb *iocb, nr_got = find_get_pages_contig(mapping, index, nr, pages); if (nr_got) goto got_pages; - - pages[0] = generic_file_buffered_read_no_cached_page(iocb, iter); - err = PTR_ERR_OR_ZERO(pages[0]); - if (!IS_ERR_OR_NULL(pages[0])) + err = filemap_new_page(iocb, iter, &pages[0]); + if (!err) nr_got = 1; got_pages: for (i = 0; i < nr_got; i++) { err = filemap_make_page_uptodate(iocb, iter, pages[i], index + i, i == 0); if (err) { - if (err == AOP_TRUNCATED_PAGE) - err = 0; for (j = i + 1; j < nr_got; j++) put_page(pages[j]); nr_got = i; @@ -2387,12 +2369,9 @@ static int generic_file_buffered_read_get_pages(struct kiocb *iocb, if (likely(nr_got)) return nr_got; - if (err) - return err; - /* - * No pages and no error means we raced and should retry: - */ - goto find_page; + if (err == -EEXIST || err == AOP_TRUNCATED_PAGE) + goto find_page; + return err; } /** -- 2.28.0