Commit e1d2699b authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFS: Avoid duplicate uncached readdir calls on eof

If we've reached the end of the directory, then cache that information
in the context so that we don't need to do an uncached readdir in order
to rediscover that fact.

Fixes: 794092c5 ("NFS: Do uncached readdir when we're seeking a cookie in an empty page cache")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent ce292d8f
...@@ -80,6 +80,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir ...@@ -80,6 +80,7 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
ctx->dir_cookie = 0; ctx->dir_cookie = 0;
ctx->dup_cookie = 0; ctx->dup_cookie = 0;
ctx->page_index = 0; ctx->page_index = 0;
ctx->eof = false;
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))
...@@ -168,6 +169,7 @@ struct nfs_readdir_descriptor { ...@@ -168,6 +169,7 @@ struct nfs_readdir_descriptor {
unsigned int cache_entry_index; unsigned int cache_entry_index;
signed char duped; signed char duped;
bool plus; bool plus;
bool eob;
bool eof; bool eof;
}; };
...@@ -989,7 +991,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, ...@@ -989,7 +991,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
ent = &array->array[i]; ent = &array->array[i];
if (!dir_emit(desc->ctx, ent->name, ent->name_len, if (!dir_emit(desc->ctx, ent->name, ent->name_len,
nfs_compat_user_ino64(ent->ino), ent->d_type)) { nfs_compat_user_ino64(ent->ino), ent->d_type)) {
desc->eof = true; desc->eob = true;
break; break;
} }
memcpy(desc->verf, verf, sizeof(desc->verf)); memcpy(desc->verf, verf, sizeof(desc->verf));
...@@ -1005,7 +1007,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc, ...@@ -1005,7 +1007,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
desc->duped = 1; desc->duped = 1;
} }
if (array->page_is_eof) if (array->page_is_eof)
desc->eof = true; desc->eof = !desc->eob;
kunmap(desc->page); kunmap(desc->page);
dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %llu\n", dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %llu\n",
...@@ -1048,7 +1050,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc) ...@@ -1048,7 +1050,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
status = nfs_readdir_xdr_to_array(desc, desc->verf, verf, arrays, sz); status = nfs_readdir_xdr_to_array(desc, desc->verf, verf, arrays, sz);
for (i = 0; !desc->eof && i < sz && arrays[i]; i++) { for (i = 0; !desc->eob && i < sz && arrays[i]; i++) {
desc->page = arrays[i]; desc->page = arrays[i];
nfs_do_filldir(desc, verf); nfs_do_filldir(desc, verf);
} }
...@@ -1107,9 +1109,15 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1107,9 +1109,15 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
desc->duped = dir_ctx->duped; desc->duped = dir_ctx->duped;
page_index = dir_ctx->page_index; page_index = dir_ctx->page_index;
desc->attr_gencount = dir_ctx->attr_gencount; desc->attr_gencount = dir_ctx->attr_gencount;
desc->eof = dir_ctx->eof;
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 (desc->eof) {
res = 0;
goto out_free;
}
if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) && if (test_and_clear_bit(NFS_INO_FORCE_READDIR, &nfsi->flags) &&
list_is_singular(&nfsi->open_files)) list_is_singular(&nfsi->open_files))
invalidate_mapping_pages(inode->i_mapping, page_index + 1, -1); invalidate_mapping_pages(inode->i_mapping, page_index + 1, -1);
...@@ -1143,7 +1151,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1143,7 +1151,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
nfs_do_filldir(desc, nfsi->cookieverf); nfs_do_filldir(desc, nfsi->cookieverf);
nfs_readdir_page_unlock_and_put_cached(desc); nfs_readdir_page_unlock_and_put_cached(desc);
} while (!desc->eof); } while (!desc->eob && !desc->eof);
spin_lock(&file->f_lock); spin_lock(&file->f_lock);
dir_ctx->dir_cookie = desc->dir_cookie; dir_ctx->dir_cookie = desc->dir_cookie;
...@@ -1151,9 +1159,10 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1151,9 +1159,10 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
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; dir_ctx->page_index = desc->page_index;
dir_ctx->eof = desc->eof;
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);
out_free:
kfree(desc); kfree(desc);
out: out:
...@@ -1195,6 +1204,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence) ...@@ -1195,6 +1204,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
if (offset == 0) if (offset == 0)
memset(dir_ctx->verf, 0, sizeof(dir_ctx->verf)); memset(dir_ctx->verf, 0, sizeof(dir_ctx->verf));
dir_ctx->duped = 0; dir_ctx->duped = 0;
dir_ctx->eof = false;
} }
spin_unlock(&filp->f_lock); spin_unlock(&filp->f_lock);
return offset; return offset;
......
...@@ -107,6 +107,7 @@ struct nfs_open_dir_context { ...@@ -107,6 +107,7 @@ struct nfs_open_dir_context {
__u64 dup_cookie; __u64 dup_cookie;
pgoff_t page_index; pgoff_t page_index;
signed char duped; signed char duped;
bool eof;
}; };
/* /*
......
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