From 871cd85992b8ec4899da7dbfa74bcca3a5d7b0d1 Mon Sep 17 00:00:00 2001 From: Hao Xu Date: Tue, 29 Sep 2020 20:00:45 +0800 Subject: [PATCH 2094/2944] io_uring: fix async buffered reads when readahead is disabled to #29998112 commit c8d317aa1887b40b188ec3aaa6e9e524333caed1 upstream The async buffered reads feature is not working when readahead is turned off. There are two things to concern: - when doing retry in io_read, not only the IOCB_WAITQ flag but also the IOCB_NOWAIT flag is still set, which makes it goes to would_block phase in generic_file_buffered_read() and then return -EAGAIN. After that, the io-wq thread work is queued, and later doing the async reads in the old way. - even if we remove IOCB_NOWAIT when doing retry, the feature is still not running properly, since in generic_file_buffered_read() it goes to lock_page_killable() after calling mapping->a_ops->readpage() to do IO, and thus causing process to sleep. Fixes: 1a0a7853b901 ("mm: support async buffered reads in generic_file_buffered_read()") Fixes: 3b2a4439e0ae ("io_uring: get rid of kiocb_wait_page_queue_init()") Signed-off-by: Hao Xu Signed-off-by: Jens Axboe Reviewed-by: Joseph Qi --- fs/io_uring.c | 1 + include/linux/pagemap.h | 1 + mm/filemap.c | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 0cabc19..0500639 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2842,6 +2842,7 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode, if (ret != 1) return ret; + req->rw.kiocb.ki_flags &= ~IOCB_WAITQ; list_del_init(&wait->entry); init_task_work(&rw->task_work, io_async_buf_retry); diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 13478a5..2dc68de 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -513,6 +513,7 @@ static inline int kiocb_wait_page_queue_init(struct kiocb *kiocb, wait->wait.flags = 0; INIT_LIST_HEAD(&wait->wait.entry); kiocb->ki_flags |= IOCB_WAITQ; + kiocb->ki_flags &= ~IOCB_NOWAIT; kiocb->ki_waitq = wait; return 0; } diff --git a/mm/filemap.c b/mm/filemap.c index 82ce70d..ea9b70f 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2324,7 +2324,11 @@ static ssize_t generic_file_buffered_read(struct kiocb *iocb, } if (!PageUptodate(page)) { - error = lock_page_killable(page); + if (iocb->ki_flags & IOCB_WAITQ) + error = lock_page_async(page, iocb->ki_waitq); + else + error = lock_page_killable(page); + if (unlikely(error)) goto readpage_error; if (!PageUptodate(page)) { -- 1.8.3.1