Commit ff81dfb5 authored by Trond Myklebust's avatar Trond Myklebust

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: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Tested-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Reviewed-by: default avatarBenjamin Coddington <bcodding@redhat.com>
parent 2929bc33
...@@ -78,6 +78,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir ...@@ -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->attr_gencount = nfsi->attr_gencount;
ctx->dir_cookie = 0; ctx->dir_cookie = 0;
ctx->dup_cookie = 0; ctx->dup_cookie = 0;
ctx->page_index = 0;
spin_lock(&dir->i_lock); spin_lock(&dir->i_lock);
if (list_empty(&nfsi->open_files) && if (list_empty(&nfsi->open_files) &&
(nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER)) (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 ...@@ -85,6 +86,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
NFS_INO_INVALID_DATA | NFS_INO_INVALID_DATA |
NFS_INO_REVAL_FORCED); NFS_INO_REVAL_FORCED);
list_add(&ctx->list, &nfsi->open_files); list_add(&ctx->list, &nfsi->open_files);
clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags);
spin_unlock(&dir->i_lock); spin_unlock(&dir->i_lock);
return ctx; return ctx;
} }
...@@ -627,8 +629,7 @@ void nfs_force_use_readdirplus(struct inode *dir) ...@@ -627,8 +629,7 @@ void nfs_force_use_readdirplus(struct inode *dir)
if (nfs_server_capable(dir, NFS_CAP_READDIRPLUS) && if (nfs_server_capable(dir, NFS_CAP_READDIRPLUS) &&
!list_empty(&nfsi->open_files)) { !list_empty(&nfsi->open_files)) {
set_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags); set_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags);
invalidate_mapping_pages(dir->i_mapping, set_bit(NFS_INO_FORCE_READDIR, &nfsi->flags);
nfsi->page_index + 1, -1);
} }
} }
...@@ -938,10 +939,8 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc) ...@@ -938,10 +939,8 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc)
sizeof(nfsi->cookieverf)); sizeof(nfsi->cookieverf));
} }
res = nfs_readdir_search_array(desc); res = nfs_readdir_search_array(desc);
if (res == 0) { if (res == 0)
nfsi->page_index = desc->page_index;
return 0; return 0;
}
nfs_readdir_page_unlock_and_put_cached(desc); nfs_readdir_page_unlock_and_put_cached(desc);
return res; return res;
} }
...@@ -1080,6 +1079,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1080,6 +1079,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_open_dir_context *dir_ctx = file->private_data; struct nfs_open_dir_context *dir_ctx = file->private_data;
struct nfs_readdir_descriptor *desc; struct nfs_readdir_descriptor *desc;
pgoff_t page_index;
int res; int res;
dfprintk(FILE, "NFS: readdir(%pD2) starting at cookie %llu\n", 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) ...@@ -1110,10 +1110,15 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
desc->dir_cookie = dir_ctx->dir_cookie; desc->dir_cookie = dir_ctx->dir_cookie;
desc->dup_cookie = dir_ctx->dup_cookie; desc->dup_cookie = dir_ctx->dup_cookie;
desc->duped = dir_ctx->duped; desc->duped = dir_ctx->duped;
page_index = dir_ctx->page_index;
desc->attr_gencount = dir_ctx->attr_gencount; desc->attr_gencount = dir_ctx->attr_gencount;
memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf)); memcpy(desc->verf, dir_ctx->verf, sizeof(desc->verf));
spin_unlock(&file->f_lock); 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 { do {
res = readdir_search_pagecache(desc); res = readdir_search_pagecache(desc);
...@@ -1150,6 +1155,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1150,6 +1155,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
dir_ctx->dup_cookie = desc->dup_cookie; dir_ctx->dup_cookie = desc->dup_cookie;
dir_ctx->duped = desc->duped; dir_ctx->duped = desc->duped;
dir_ctx->attr_gencount = desc->attr_gencount; dir_ctx->attr_gencount = desc->attr_gencount;
dir_ctx->page_index = desc->page_index;
memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf)); memcpy(dir_ctx->verf, desc->verf, sizeof(dir_ctx->verf));
spin_unlock(&file->f_lock); spin_unlock(&file->f_lock);
......
...@@ -103,6 +103,7 @@ struct nfs_open_dir_context { ...@@ -103,6 +103,7 @@ struct nfs_open_dir_context {
__be32 verf[NFS_DIR_VERIFIER_SIZE]; __be32 verf[NFS_DIR_VERIFIER_SIZE];
__u64 dir_cookie; __u64 dir_cookie;
__u64 dup_cookie; __u64 dup_cookie;
pgoff_t page_index;
signed char duped; signed char duped;
}; };
...@@ -181,9 +182,6 @@ struct nfs_inode { ...@@ -181,9 +182,6 @@ struct nfs_inode {
struct rw_semaphore rmdir_sem; struct rw_semaphore rmdir_sem;
struct mutex commit_mutex; struct mutex commit_mutex;
/* track last access to cached pages */
unsigned long page_index;
#if IS_ENABLED(CONFIG_NFS_V4) #if IS_ENABLED(CONFIG_NFS_V4)
struct nfs4_cached_acl *nfs4_acl; struct nfs4_cached_acl *nfs4_acl;
/* NFSv4 state */ /* NFSv4 state */
...@@ -272,6 +270,7 @@ struct nfs4_copy_state { ...@@ -272,6 +270,7 @@ struct nfs4_copy_state {
#define NFS_INO_INVALIDATING (3) /* inode is being invalidated */ #define NFS_INO_INVALIDATING (3) /* inode is being invalidated */
#define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */ #define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */
#define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */ #define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */
#define NFS_INO_FORCE_READDIR (7) /* force readdirplus */
#define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */ #define NFS_INO_LAYOUTCOMMIT (9) /* layoutcommit required */
#define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */ #define NFS_INO_LAYOUTCOMMITTING (10) /* layoutcommit inflight */
#define NFS_INO_LAYOUTSTATS (11) /* layoutstats inflight */ #define NFS_INO_LAYOUTSTATS (11) /* layoutstats inflight */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment