--- /dev/null
+From e0340f16a08d031de54ed91d26f57c9a966a776a Mon Sep 17 00:00:00 2001
+From: Dave Wysochanski <dwysocha@redhat.com>
+Date: Tue, 29 Jun 2021 05:11:28 -0400
+Subject: NFS: Ensure nfs_readpage returns promptly when internal error occurs
+
+From: Dave Wysochanski <dwysocha@redhat.com>
+
+commit e0340f16a08d031de54ed91d26f57c9a966a776a upstream.
+
+A previous refactoring of nfs_readpage() might end up calling
+wait_on_page_locked_killable() even if readpage_async_filler() failed
+with an internal error and pg_error was non-zero (for example, if
+nfs_create_request() failed). In the case of an internal error,
+skip over wait_on_page_locked_killable() as this is only needed
+when the read is sent and an error occurs during completion handling.
+
+Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfs/read.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -374,10 +374,10 @@ int nfs_readpage(struct file *file, stru
+ &nfs_async_read_completion_ops);
+
+ ret = readpage_async_filler(&desc, page);
++ if (ret)
++ goto out;
+
+- if (!ret)
+- nfs_pageio_complete_read(&desc.pgio, inode);
+-
++ nfs_pageio_complete_read(&desc.pgio, inode);
+ ret = desc.pgio.pg_error < 0 ? desc.pgio.pg_error : 0;
+ if (!ret) {
+ ret = wait_on_page_locked_killable(page);
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
- fs/nfs/fscache.c | 18 +++++++++++++-----
- fs/nfs/read.c | 5 +++--
+ fs/nfs/fscache.c | 18 +++++++++++++-----
+ fs/nfs/read.c | 5 +++--
2 files changed, 16 insertions(+), 7 deletions(-)
-diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
-index c4c021c6ebbd..d743629e05e1 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
-@@ -385,12 +385,15 @@ static void nfs_readpage_from_fscache_complete(struct page *page,
+@@ -385,12 +385,15 @@ static void nfs_readpage_from_fscache_co
"NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n",
page, context, error);
}
/*
-@@ -405,6 +408,11 @@ int __nfs_readpage_from_fscache(struct nfs_open_context *ctx,
+@@ -405,6 +408,11 @@ int __nfs_readpage_from_fscache(struct n
"NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
nfs_i_fscache(inode), page, page->index, page->flags, inode);
ret = fscache_read_or_alloc_page(nfs_i_fscache(inode),
page,
nfs_readpage_from_fscache_complete,
-diff --git a/fs/nfs/read.c b/fs/nfs/read.c
-index d2b6dce1f99f..4ca50b70a7b0 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
-@@ -363,13 +363,13 @@ int nfs_readpage(struct file *file, struct page *page)
+@@ -363,13 +363,13 @@ int nfs_readpage(struct file *file, stru
} else
desc.ctx = get_nfs_open_context(nfs_file_open_context(file));
nfs_pageio_init_read(&desc.pgio, inode, false,
&nfs_async_read_completion_ops);
-@@ -379,6 +379,7 @@ int nfs_readpage(struct file *file, struct page *page)
- nfs_pageio_complete_read(&desc.pgio, inode);
+@@ -379,6 +379,7 @@ int nfs_readpage(struct file *file, stru
+ nfs_pageio_complete_read(&desc.pgio, inode);
ret = desc.pgio.pg_error < 0 ? desc.pgio.pg_error : 0;
+out_wait:
if (!ret) {
ret = wait_on_page_locked_killable(page);
if (!PageUptodate(page) && !ret)
---
-2.30.2
-