aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 254e5b21b915..d07f704a2ac9 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2188,6 +2188,15 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
2188 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); 2188 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
2189 if (IS_ERR(dentry)) 2189 if (IS_ERR(dentry))
2190 return nfserrno(PTR_ERR(dentry)); 2190 return nfserrno(PTR_ERR(dentry));
2191 if (!dentry->d_inode) {
2192 /*
2193 * nfsd_buffered_readdir drops the i_mutex between
2194 * readdir and calling this callback, leaving a window
2195 * where this directory entry could have gone away.
2196 */
2197 dput(dentry);
2198 return nfserr_noent;
2199 }
2191 2200
2192 exp_get(exp); 2201 exp_get(exp);
2193 /* 2202 /*
@@ -2250,6 +2259,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2250 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); 2259 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
2251 int buflen; 2260 int buflen;
2252 __be32 *p = cd->buffer; 2261 __be32 *p = cd->buffer;
2262 __be32 *cookiep;
2253 __be32 nfserr = nfserr_toosmall; 2263 __be32 nfserr = nfserr_toosmall;
2254 2264
2255 /* In nfsv4, "." and ".." never make it onto the wire.. */ 2265 /* In nfsv4, "." and ".." never make it onto the wire.. */
@@ -2266,7 +2276,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2266 goto fail; 2276 goto fail;
2267 2277
2268 *p++ = xdr_one; /* mark entry present */ 2278 *p++ = xdr_one; /* mark entry present */
2269 cd->offset = p; /* remember pointer */ 2279 cookiep = p;
2270 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ 2280 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
2271 p = xdr_encode_array(p, name, namlen); /* name length & name */ 2281 p = xdr_encode_array(p, name, namlen); /* name length & name */
2272 2282
@@ -2280,6 +2290,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2280 goto fail; 2290 goto fail;
2281 case nfserr_dropit: 2291 case nfserr_dropit:
2282 goto fail; 2292 goto fail;
2293 case nfserr_noent:
2294 goto skip_entry;
2283 default: 2295 default:
2284 /* 2296 /*
2285 * If the client requested the RDATTR_ERROR attribute, 2297 * If the client requested the RDATTR_ERROR attribute,
@@ -2298,6 +2310,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2298 } 2310 }
2299 cd->buflen -= (p - cd->buffer); 2311 cd->buflen -= (p - cd->buffer);
2300 cd->buffer = p; 2312 cd->buffer = p;
2313 cd->offset = cookiep;
2314skip_entry:
2301 cd->common.err = nfs_ok; 2315 cd->common.err = nfs_ok;
2302 return 0; 2316 return 0;
2303fail: 2317fail: