summaryrefslogtreecommitdiff
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2021-09-28 21:33:44 +0300
committerTrond Myklebust <trond.myklebust@hammerspace.com>2021-10-04 03:49:07 +0300
commitff81dfb5d721fff87bd516c558847f6effb70031 (patch)
tree02a2a6df1a54f8403d624215ca0639b96e1ea8e6 /fs/nfs
parent2929bc3329f4c7e4df400acca2b1844492650bfd (diff)
downloadlinux-ff81dfb5d721fff87bd516c558847f6effb70031.tar.xz
NFS: Further optimisations for 'ls -l'
If a user is doing 'ls -l', we have a heuristic in GETATTR that tells the readdir code to try to use READDIRPLUS in order to refresh the inode attributes. In certain cirumstances, we also try to invalidate the remaining directory entries in order to ensure this refresh. If there are multiple readers of the directory, we probably should avoid invalidating the page cache, since the heuristic breaks down in that situation anyway. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Tested-by: Benjamin Coddington <bcodding@redhat.com> Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index fa4d33687d2b..33cfff8ea551 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -78,6 +78,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
ctx->attr_gencount = nfsi->attr_gencount;
ctx->dir_cookie = 0;
ctx->dup_cookie = 0;
+ ctx->page_index = 0;
spin_lock(&dir->i_lock);
if (list_empty(&nfsi->open_files) &&
(nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
@@ -85,6 +86,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
NFS_INO_INVALID_DATA |
NFS_INO_REVAL_FORCED);
list_add(&ctx->list, &nfsi->open_files);
+ clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags);
spin_unlock(&dir->i_lock);
return ctx;
}
@@ -627,8 +629,7 @@ void nfs_force_use_readdirplus(struct inode *dir)
if (nfs_server_capable(dir, NFS_CAP_READDIRPLUS) &&
!list_empty(&nfsi->open_files)) {
set_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags);
- invalidate_mapping_pages(dir->i_mapping,
- nfsi->page_index + 1, -1);
+ set_bit(NFS_INO_FORCE_READDIR, &nfsi->flags);
}
}
@@ -938,10 +939,8 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc)
sizeof(nfsi->cookieverf));
}
res = nfs_readdir_search_array(desc);
- if (res == 0) {
- nfsi->page_index = desc->page_index;
+ if (res == 0)
return 0;
- }
nfs_readdir_page_unlock_and_put_cached(desc);
return res;
}
@@ -1080,6 +1079,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_open_dir_context *dir_ctx = file->private_data;
struct nfs_readdir_descriptor *desc;
+ pgoff_t page_index;
int res;
dfprintk(FILE, "NFS: readdir(%pD2) starting at cookie %llu\n",
@@ -1110,10 +1110,15 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
desc->dir_cookie = dir_ctx->dir_cookie;
desc->dup_cookie = dir_ctx->dup_cookie;
desc->duped = dir_ctx->duped;
+ page_index = dir_ctx->page_index;
desc->attr_gencount = dir_ctx->attr_gencount;
memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf));
spin_unlock(&file->f_lock);
+ if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) &&
+ list_is_singular(&nfsi->open_files))
+ invalidate_mapping_pages(inode->i_mapping, page_index + 1, -1);
+
do {
res = readdir_search_pagecache(desc);
@@ -1150,6 +1155,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
dir_ctx->dup_cookie = desc->dup_cookie;
dir_ctx->duped = desc->duped;
dir_ctx->attr_gencount = desc->attr_gencount;
+ dir_ctx->page_index = desc->page_index;
memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf));
spin_unlock(&file->f_lock);