mm/filemap: move the iocb checks into filemap_update_page
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Wed, 24 Feb 2021 20:02:25 +0000 (12:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 24 Feb 2021 21:38:28 +0000 (13:38 -0800)
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>
mm/filemap.c

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