mm/filemap: move the iocb checks into filemap_update_page

We don't need to give up when a non-blocking request sees a !Uptodate
page.  We may be able to satisfy the read from a partially-uptodate page.

Link: https://lkml.kernel.org/r/20210122160140.223228-13-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:
Matthew Wilcox (Oracle) 2021-02-24 12:02:25 -08:00 committed by Linus Torvalds
parent 4612aeef09
commit 87d1d7b688
1 changed files with 10 additions and 14 deletions

View File

@ -2240,15 +2240,16 @@ static int filemap_update_page(struct kiocb *iocb,
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
int error; int error;
if (iocb->ki_flags & IOCB_WAITQ) { if (!trylock_page(page)) {
error = lock_page_async(page, iocb->ki_waitq); if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_NOIO))
if (error) return -EAGAIN;
return error; if (!(iocb->ki_flags & IOCB_WAITQ)) {
} else {
if (!trylock_page(page)) {
put_and_wait_on_page_locked(page, TASK_KILLABLE); put_and_wait_on_page_locked(page, TASK_KILLABLE);
return AOP_TRUNCATED_PAGE; return AOP_TRUNCATED_PAGE;
} }
error = __lock_page_async(page, iocb->ki_waitq);
if (error)
return error;
} }
if (!page->mapping) if (!page->mapping)
@ -2366,14 +2367,9 @@ static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter,
} }
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
if ((iocb->ki_flags & IOCB_NOWAIT) || if ((iocb->ki_flags & IOCB_WAITQ) &&
((iocb->ki_flags & IOCB_WAITQ) && pvec->nr > 1)) { pagevec_count(pvec) > 1)
put_page(page); iocb->ki_flags |= IOCB_NOWAIT;
pvec->nr--;
err = -EAGAIN;
goto err;
}
err = filemap_update_page(iocb, mapping, iter, page, err = filemap_update_page(iocb, mapping, iter, page,
pg_pos, pg_count); pg_pos, pg_count);
if (err) { if (err) {