Commit 13884ff2 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Fix handling of cookie verifier in uncached_readdir()

If we're doing uncached readdir(), then the readdir cookie could be
different from the one cached in the nfs_inode. We should therefore
ensure that we save that one in the struct nfs_open_dir_context.

Fixes: 35df59d3 ("NFS: Reduce number of RPC calls when doing uncached readdir")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent ee3707ae
...@@ -976,10 +976,10 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc) ...@@ -976,10 +976,10 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc)
/* /*
* Once we've found the start of the dirent within a page: fill 'er up... * Once we've found the start of the dirent within a page: fill 'er up...
*/ */
static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
const __be32 *verf)
{ {
struct file *file = desc->file; struct file *file = desc->file;
struct nfs_inode *nfsi = NFS_I(file_inode(file));
struct nfs_cache_array *array; struct nfs_cache_array *array;
unsigned int i = 0; unsigned int i = 0;
...@@ -993,7 +993,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) ...@@ -993,7 +993,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc)
desc->eof = true; desc->eof = true;
break; break;
} }
memcpy(desc->verf, nfsi->cookieverf, sizeof(desc->verf)); memcpy(desc->verf, verf, sizeof(desc->verf));
if (i < (array->size-1)) if (i < (array->size-1))
desc->dir_cookie = array->array[i+1].cookie; desc->dir_cookie = array->array[i+1].cookie;
else else
...@@ -1050,7 +1050,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc) ...@@ -1050,7 +1050,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
for (i = 0; !desc->eof && i < sz && arrays[i]; i++) { for (i = 0; !desc->eof && i < sz && arrays[i]; i++) {
desc->page = arrays[i]; desc->page = arrays[i];
nfs_do_filldir(desc); nfs_do_filldir(desc, verf);
} }
desc->page = NULL; desc->page = NULL;
...@@ -1071,6 +1071,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1071,6 +1071,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
{ {
struct dentry *dentry = file_dentry(file); struct dentry *dentry = file_dentry(file);
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
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;
int res; int res;
...@@ -1124,7 +1125,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1124,7 +1125,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
break; break;
} }
if (res == -ETOOSMALL && desc->plus) { if (res == -ETOOSMALL && desc->plus) {
clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); clear_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags);
nfs_zap_caches(inode); nfs_zap_caches(inode);
desc->page_index = 0; desc->page_index = 0;
desc->plus = false; desc->plus = false;
...@@ -1134,7 +1135,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) ...@@ -1134,7 +1135,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
if (res < 0) if (res < 0)
break; break;
nfs_do_filldir(desc); 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->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