We don't need to give up when a special request sees a !Uptodate page. We may be able to satisfy the read from a partially-uptodate page. Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> --- mm/filemap.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index ebb14fdec0cc..41b90243f4ee 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2230,17 +2230,21 @@ static int filemap_read_page(struct file *file, struct address_space *mapping, static int filemap_update_page(struct kiocb *iocb, struct address_space *mapping, struct iov_iter *iter, - struct page *page, loff_t pos, loff_t count) + struct page *page, loff_t pos, loff_t count, bool first) { struct inode *inode = mapping->host; - int error; + int error = -EAGAIN; - if (iocb->ki_flags & IOCB_WAITQ) { - error = lock_page_async(page, iocb->ki_waitq); - if (error) + if (!trylock_page(page)) { + if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_NOIO)) goto error; - } else { - if (!trylock_page(page)) { + if (iocb->ki_flags & IOCB_WAITQ) { + if (!first) + goto error; + error = __lock_page_async(page, iocb->ki_waitq); + if (error) + goto error; + } else { put_and_wait_on_page_locked(page, TASK_KILLABLE); return AOP_TRUNCATED_PAGE; } @@ -2359,16 +2363,8 @@ static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter, } if (!PageUptodate(page)) { - if ((iocb->ki_flags & IOCB_NOWAIT) || - ((iocb->ki_flags & IOCB_WAITQ) && nr_got > 1)) { - put_page(page); - nr_got--; - err = -EAGAIN; - goto err; - } - err = filemap_update_page(iocb, mapping, iter, page, - pg_pos, pg_count); + pg_pos, pg_count, nr_got == 1); if (err) nr_got--; } -- 2.28.0