@@ -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--;
}
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@infradead.org> --- mm/filemap.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-)