diff mbox series

[v8,24/24] NFS: Cache all entries in the readdirplus reply

Message ID 20220225182829.1236093-25-trondmy@kernel.org (mailing list archive)
State New, archived
Headers show
Series Readdir improvements | expand

Commit Message

Trond Myklebust Feb. 25, 2022, 6:28 p.m. UTC
From: Trond Myklebust <trond.myklebust@hammerspace.com>

Even if we're not able to cache all the entries in the readdir buffer,
let's ensure that we do prime the dcache.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 fs/nfs/dir.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 71f61565c72c..5e9c25a562bf 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -789,7 +789,7 @@  static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
 	struct xdr_stream stream;
 	struct xdr_buf buf;
 	struct page *scratch, *new, *page = *arrays;
-	int status;
+	int err, status = 0;
 
 	scratch = alloc_page(GFP_KERNEL);
 	if (scratch == NULL)
@@ -802,25 +802,32 @@  static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
 		if (entry->fattr->label)
 			entry->fattr->label->len = NFS4_MAXLABELLEN;
 
-		status = xdr_decode(desc, entry, &stream);
-		if (status != 0)
+		err = xdr_decode(desc, entry, &stream);
+		if (err != 0) {
+			if (!status)
+				status = err;
 			break;
+		}
 
-		if (desc->plus)
+		if (desc->plus) {
 			nfs_prime_dcache(file_dentry(desc->file), entry,
-					desc->dir_verifier);
+					 desc->dir_verifier);
+			if (status == -ENOSPC)
+				continue;
+		}
 
 		status = nfs_readdir_add_to_array(entry, page);
 		if (status != -ENOSPC)
 			continue;
 
 		if (page->mapping != mapping) {
-			if (!--narrays)
-				break;
+			if (narrays <= 1)
+				continue;
 			new = nfs_readdir_page_array_alloc(entry->prev_cookie,
 							   GFP_KERNEL);
 			if (!new)
-				break;
+				continue;
+			narrays--;
 			arrays++;
 			*arrays = page = new;
 		} else {
@@ -829,14 +836,14 @@  static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
 							change_attr,
 							desc->clear_cache);
 			if (!new)
-				break;
+				continue;
 			if (page != *arrays)
 				nfs_readdir_page_unlock_and_put(page);
 			page = new;
 		}
 		desc->page_index_max++;
 		status = nfs_readdir_add_to_array(entry, page);
-	} while (!status && !entry->eof);
+	} while ((!status || (status == -ENOSPC && desc->plus)) && !entry->eof);
 
 	switch (status) {
 	case -EBADCOOKIE: