diff options
author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2020-11-02 20:11:32 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2020-12-02 14:05:52 -0500 |
commit | 9fff59ed4c4d239125f8529a9971c46defd2e2b0 (patch) | |
tree | 92590d39069dcfba43b98bfdba764f244d309e22 /fs/nfs | |
parent | 82e22a5e6245873779db1607d3b0fec6f9ca07d0 (diff) | |
download | linux-9fff59ed4c4d239125f8529a9971c46defd2e2b0.tar.bz2 |
NFS: Handle NFS4ERR_NOT_SAME and NFSERR_BADCOOKIE from readdir calls
If the server returns NFS4ERR_NOT_SAME or tells us that the cookie is
bad in response to a READDIR call, then we should empty the page cache
so that we can fill it from scratch again.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Tested-by: Benjamin Coddington <bcodding@redhat.com>
Tested-by: Dave Wysochanski <dwysocha@redhat.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 24 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 |
2 files changed, 18 insertions, 8 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3ee0668a9719..3b44bef3a1b4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -861,15 +861,21 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc) return -ENOMEM; if (nfs_readdir_page_needs_filling(desc->page)) { res = nfs_readdir_xdr_to_array(desc, desc->page, inode); - if (res < 0) - goto error; + if (res < 0) { + nfs_readdir_page_unlock_and_put_cached(desc); + if (res == -EBADCOOKIE || res == -ENOTSYNC) { + invalidate_inode_pages2(desc->file->f_mapping); + desc->page_index = 0; + return -EAGAIN; + } + return res; + } } res = nfs_readdir_search_array(desc); if (res == 0) { nfsi->page_index = desc->page_index; return 0; } -error: nfs_readdir_page_unlock_and_put_cached(desc); return res; } @@ -879,12 +885,12 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc) { int res; - if (desc->page_index == 0) { - desc->current_index = 0; - desc->prev_index = 0; - desc->last_cookie = 0; - } do { + if (desc->page_index == 0) { + desc->current_index = 0; + desc->prev_index = 0; + desc->last_cookie = 0; + } res = find_and_lock_cache_page(desc); } while (res == -EAGAIN); return res; @@ -1030,6 +1036,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) res = uncached_readdir(desc); if (res == 0) continue; + if (res == -EBADCOOKIE || res == -ENOTSYNC) + res = 0; } break; } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index adcaba68eaed..7ab40d0e6a74 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -184,6 +184,8 @@ static int nfs4_map_errors(int err) return -EPROTONOSUPPORT; case -NFS4ERR_FILE_OPEN: return -EBUSY; + case -NFS4ERR_NOT_SAME: + return -ENOTSYNC; default: dprintk("%s could not handle NFSv4 error %d\n", __func__, -err); |