Move the calculation of the per-page variables and the readahead handling from the only caller into generic_file_buffered_read_pagenotuptodate, which now becomes a routine to handle everything related to bringing one page uptodate and thus is renamed to filemap_read_one_page. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- mm/filemap.c | 63 +++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index bae5b905aa7bdc..5cdf8090d4e12c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2217,13 +2217,26 @@ static int filemap_readpage(struct kiocb *iocb, struct page *page) return error; } -static int generic_file_buffered_read_pagenotuptodate(struct kiocb *iocb, - struct iov_iter *iter, struct page *page, loff_t pos, - loff_t count, bool first) +static int filemap_make_page_uptodate(struct kiocb *iocb, struct iov_iter *iter, + struct page *page, pgoff_t pg_index, bool first) { - struct address_space *mapping = iocb->ki_filp->f_mapping; + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + loff_t last = iocb->ki_pos + iter->count; + pgoff_t last_index = (last + PAGE_SIZE - 1) >> PAGE_SHIFT; + loff_t pos = max(iocb->ki_pos, (loff_t)pg_index << PAGE_SHIFT); int error = -EAGAIN; + if (PageReadahead(page)) { + if (iocb->ki_flags & IOCB_NOIO) + goto put_page; + page_cache_async_readahead(mapping, &file->f_ra, file, page, + pg_index, last_index - pg_index); + } + + if (PageUptodate(page)) + return 0; + if (iocb->ki_flags & IOCB_NOWAIT) goto put_page; @@ -2255,8 +2268,8 @@ static int generic_file_buffered_read_pagenotuptodate(struct kiocb *iocb, /* Did it get truncated before we got the lock? */ if (!page->mapping) goto page_not_up_to_date_locked; - if (!mapping->a_ops->is_partially_uptodate(page, - pos & ~PAGE_MASK, count)) + if (!mapping->a_ops->is_partially_uptodate(page, pos & ~PAGE_MASK, + last - pos)) goto page_not_up_to_date_locked; unlock_page: @@ -2360,35 +2373,15 @@ static int generic_file_buffered_read_get_pages(struct kiocb *iocb, nr_got = 1; got_pages: for (i = 0; i < nr_got; i++) { - struct page *page = pages[i]; - pgoff_t pg_index = index + i; - loff_t pg_pos = max(iocb->ki_pos, - (loff_t) pg_index << PAGE_SHIFT); - loff_t pg_count = iocb->ki_pos + iter->count - pg_pos; - - if (PageReadahead(page)) { - if (iocb->ki_flags & IOCB_NOIO) { - for (j = i; j < nr_got; j++) - put_page(pages[j]); - nr_got = i; - err = -EAGAIN; - break; - } - page_cache_async_readahead(mapping, ra, filp, page, - pg_index, last_index - pg_index); - } - - if (!PageUptodate(page)) { - err = generic_file_buffered_read_pagenotuptodate(iocb, - iter, page, pg_pos, pg_count, 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; - break; - } + 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; + break; } } -- 2.28.0