aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4recover.c4
-rw-r--r--fs/nfsd/nfs4state.c1
-rw-r--r--fs/nfsd/nfs4xdr.c16
3 files changed, 17 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 5275097a7565..b5348405046b 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -229,7 +229,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
229 goto out; 229 goto out;
230 status = vfs_readdir(filp, nfsd4_build_namelist, &names); 230 status = vfs_readdir(filp, nfsd4_build_namelist, &names);
231 fput(filp); 231 fput(filp);
232 mutex_lock(&dir->d_inode->i_mutex); 232 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
233 while (!list_empty(&names)) { 233 while (!list_empty(&names)) {
234 entry = list_entry(names.next, struct name_list, list); 234 entry = list_entry(names.next, struct name_list, list);
235 235
@@ -264,7 +264,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
264 264
265 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 265 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
266 266
267 mutex_lock(&rec_dir.dentry->d_inode->i_mutex); 267 mutex_lock_nested(&rec_dir.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
268 dentry = lookup_one_len(name, rec_dir.dentry, namlen); 268 dentry = lookup_one_len(name, rec_dir.dentry, namlen);
269 if (IS_ERR(dentry)) { 269 if (IS_ERR(dentry)) {
270 status = PTR_ERR(dentry); 270 status = PTR_ERR(dentry);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index c65a27b76a9d..3b711f5147a7 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -580,7 +580,6 @@ free_session(struct kref *kref)
580 struct nfsd4_cache_entry *e = &ses->se_slots[i].sl_cache_entry; 580 struct nfsd4_cache_entry *e = &ses->se_slots[i].sl_cache_entry;
581 nfsd4_release_respages(e->ce_respages, e->ce_resused); 581 nfsd4_release_respages(e->ce_respages, e->ce_resused);
582 } 582 }
583 kfree(ses->se_slots);
584 kfree(ses); 583 kfree(ses);
585} 584}
586 585
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index b820c311931c..b73549d293be 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2214,6 +2214,15 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
2214 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); 2214 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
2215 if (IS_ERR(dentry)) 2215 if (IS_ERR(dentry))
2216 return nfserrno(PTR_ERR(dentry)); 2216 return nfserrno(PTR_ERR(dentry));
2217 if (!dentry->d_inode) {
2218 /*
2219 * nfsd_buffered_readdir drops the i_mutex between
2220 * readdir and calling this callback, leaving a window
2221 * where this directory entry could have gone away.
2222 */
2223 dput(dentry);
2224 return nfserr_noent;
2225 }
2217 2226
2218 exp_get(exp); 2227 exp_get(exp);
2219 /* 2228 /*
@@ -2276,6 +2285,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2276 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); 2285 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
2277 int buflen; 2286 int buflen;
2278 __be32 *p = cd->buffer; 2287 __be32 *p = cd->buffer;
2288 __be32 *cookiep;
2279 __be32 nfserr = nfserr_toosmall; 2289 __be32 nfserr = nfserr_toosmall;
2280 2290
2281 /* In nfsv4, "." and ".." never make it onto the wire.. */ 2291 /* In nfsv4, "." and ".." never make it onto the wire.. */
@@ -2292,7 +2302,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2292 goto fail; 2302 goto fail;
2293 2303
2294 *p++ = xdr_one; /* mark entry present */ 2304 *p++ = xdr_one; /* mark entry present */
2295 cd->offset = p; /* remember pointer */ 2305 cookiep = p;
2296 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ 2306 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
2297 p = xdr_encode_array(p, name, namlen); /* name length & name */ 2307 p = xdr_encode_array(p, name, namlen); /* name length & name */
2298 2308
@@ -2306,6 +2316,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2306 goto fail; 2316 goto fail;
2307 case nfserr_dropit: 2317 case nfserr_dropit:
2308 goto fail; 2318 goto fail;
2319 case nfserr_noent:
2320 goto skip_entry;
2309 default: 2321 default:
2310 /* 2322 /*
2311 * If the client requested the RDATTR_ERROR attribute, 2323 * If the client requested the RDATTR_ERROR attribute,
@@ -2324,6 +2336,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2324 } 2336 }
2325 cd->buflen -= (p - cd->buffer); 2337 cd->buflen -= (p - cd->buffer);
2326 cd->buffer = p; 2338 cd->buffer = p;
2339 cd->offset = cookiep;
2340skip_entry:
2327 cd->common.err = nfs_ok; 2341 cd->common.err = nfs_ok;
2328 return 0; 2342 return 0;
2329fail: 2343fail: