|
NeilBrown |
5ca83d |
From: Trond Myklebust <trond.myklebust@hammerspace.com>
|
|
NeilBrown |
5ca83d |
Date: Fri, 6 Nov 2020 20:47:05 -0500
|
|
NeilBrown |
5ca83d |
Subject: [PATCH] NFS: Do uncached readdir when we're seeking a cookie in an
|
|
NeilBrown |
5ca83d |
empty page cache
|
|
NeilBrown |
5ca83d |
Git-commit: 794092c57f89c2c833da00f82f38a0afcb4033bc
|
|
Michal Kubecek |
b7dfcc |
Patch-mainline: v5.11-rc1
|
|
NeilBrown |
ee8ec2 |
References: bsc#1191628 bsc#1192549
|
|
NeilBrown |
5ca83d |
|
|
NeilBrown |
5ca83d |
If the directory is changing, causing the page cache to get invalidated
|
|
NeilBrown |
5ca83d |
while we are listing the contents, then the NFS client is currently forced
|
|
NeilBrown |
5ca83d |
to read in the entire directory contents from scratch, because it needs
|
|
NeilBrown |
5ca83d |
to perform a linear search for the readdir cookie. While this is not
|
|
NeilBrown |
5ca83d |
an issue for small directories, it does not scale to directories with
|
|
NeilBrown |
5ca83d |
millions of entries.
|
|
NeilBrown |
5ca83d |
In order to be able to deal with large directories that are changing,
|
|
NeilBrown |
5ca83d |
add a heuristic to ensure that if the page cache is empty, and we are
|
|
NeilBrown |
5ca83d |
searching for a cookie that is not the zero cookie, we just default to
|
|
NeilBrown |
5ca83d |
performing uncached readdir.
|
|
NeilBrown |
5ca83d |
|
|
NeilBrown |
5ca83d |
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
|
|
NeilBrown |
5ca83d |
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
|
|
NeilBrown |
5ca83d |
Tested-by: Benjamin Coddington <bcodding@redhat.com>
|
|
NeilBrown |
5ca83d |
Tested-by: Dave Wysochanski <dwysocha@redhat.com>
|
|
NeilBrown |
5ca83d |
Acked-by: NeilBrown <neilb@suse.com>
|
|
NeilBrown |
5ca83d |
|
|
NeilBrown |
5ca83d |
---
|
|
NeilBrown |
5ca83d |
fs/nfs/dir.c | 17 +++++++++++++++++
|
|
NeilBrown |
5ca83d |
1 file changed, 17 insertions(+)
|
|
NeilBrown |
5ca83d |
|
|
NeilBrown |
5ca83d |
--- a/fs/nfs/dir.c
|
|
NeilBrown |
5ca83d |
+++ b/fs/nfs/dir.c
|
|
NeilBrown |
5ca83d |
@@ -743,12 +743,29 @@ error:
|
|
NeilBrown |
5ca83d |
return res;
|
|
NeilBrown |
5ca83d |
}
|
|
NeilBrown |
5ca83d |
|
|
NeilBrown |
5ca83d |
+static bool nfs_readdir_dont_search_cache(nfs_readdir_descriptor_t *desc)
|
|
NeilBrown |
5ca83d |
+{
|
|
NeilBrown |
5ca83d |
+ struct address_space *mapping = desc->file->f_mapping;
|
|
NeilBrown |
5ca83d |
+ struct inode *dir = file_inode(desc->file);
|
|
NeilBrown |
5ca83d |
+ unsigned int dtsize = NFS_SERVER(dir)->dtsize;
|
|
NeilBrown |
5ca83d |
+ loff_t size = i_size_read(dir);
|
|
NeilBrown |
5ca83d |
+
|
|
NeilBrown |
5ca83d |
+ /*
|
|
NeilBrown |
5ca83d |
+ * Default to uncached readdir if the page cache is empty, and
|
|
NeilBrown |
5ca83d |
+ * we're looking for a non-zero cookie in a large directory.
|
|
NeilBrown |
5ca83d |
+ */
|
|
NeilBrown |
ee8ec2 |
+ return *desc->dir_cookie != 0 && mapping->nrpages == 0 && size > dtsize;
|
|
NeilBrown |
5ca83d |
+}
|
|
NeilBrown |
5ca83d |
+
|
|
NeilBrown |
5ca83d |
/* Search for desc->dir_cookie from the beginning of the page cache */
|
|
NeilBrown |
5ca83d |
static inline
|
|
NeilBrown |
5ca83d |
int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
|
|
NeilBrown |
5ca83d |
{
|
|
NeilBrown |
5ca83d |
int res;
|
|
NeilBrown |
5ca83d |
|
|
NeilBrown |
5ca83d |
+ if (nfs_readdir_dont_search_cache(desc))
|
|
NeilBrown |
5ca83d |
+ return -EBADCOOKIE;
|
|
NeilBrown |
5ca83d |
+
|
|
NeilBrown |
5ca83d |
if (desc->page_index == 0) {
|
|
NeilBrown |
5ca83d |
desc->current_index = 0;
|
|
NeilBrown |
5ca83d |
desc->last_cookie = 0;
|