From 7ed433c7e1add172c12d60df14dbd3b7a0ca5462 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 16 Nov 2020 13:36:24 -0700 Subject: [PATCH 2412/2944] mm: never attempt async page lock if we've transferred data already task #31332859 commit 0abed7c69b956d135cb6d320c350b2adb213e7d8 upstream. We catch the case where we enter generic_file_buffered_read() with data already transferred, but we also need to be careful not to allow an async page lock if we're looping transferring data. If not, we could be returning -EIOCBQUEUED instead of the transferred amount, and it could result in double waitqueue additions as well. Cc: stable@vger.kernel.org # v5.9 Fixes: 1a0a7853b901 ("mm: support async buffered reads in generic_file_buffered_read()") Signed-off-by: Jens Axboe Signed-off-by: Hao Xu Reviewed-by: Joseph Qi --- mm/filemap.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 8663142..752497b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2284,10 +2284,15 @@ static ssize_t generic_file_buffered_read(struct kiocb *iocb, page_not_up_to_date: /* Get exclusive access to the page ... */ - if (iocb->ki_flags & IOCB_WAITQ) + if (iocb->ki_flags & IOCB_WAITQ) { + if (written) { + put_page(page); + goto out; + } error = lock_page_async(page, iocb->ki_waitq); - else + } else { error = lock_page_killable(page); + } if (unlikely(error)) goto readpage_error; @@ -2330,10 +2335,15 @@ static ssize_t generic_file_buffered_read(struct kiocb *iocb, } if (!PageUptodate(page)) { - if (iocb->ki_flags & IOCB_WAITQ) + if (iocb->ki_flags & IOCB_WAITQ) { + if (written) { + put_page(page); + goto out; + } error = lock_page_async(page, iocb->ki_waitq); - else + } else { error = lock_page_killable(page); + } if (unlikely(error)) goto readpage_error; -- 1.8.3.1