Commit 9fff59ed authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Tested-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Tested-by: default avatarDave Wysochanski <dwysocha@redhat.com>
parent 82e22a5e
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -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;

	do {
		if (desc->page_index == 0) {
			desc->current_index = 0;
			desc->prev_index = 0;
			desc->last_cookie = 0;
		}
	do {
		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;
		}
+2 −0
Original line number Diff line number Diff line
@@ -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);