From: NeilBrown nfsd_cross_mnt can release the reference to the passed svc_export structure when it returns a different svc_export structure. So we need to make sure we have a counted reference before, and drop the reference afterwards. --- 25-akpm/fs/nfsd/nfs4xdr.c | 3 +++ 25-akpm/fs/nfsd/vfs.c | 4 +++- 25-akpm/include/linux/nfsd/export.h | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff -puN fs/nfsd/nfs4xdr.c~knfsd-5-of-10-protect-reference-to-exp-across-calls-to-nfsd_cross_mnt fs/nfsd/nfs4xdr.c --- 25/fs/nfsd/nfs4xdr.c~knfsd-5-of-10-protect-reference-to-exp-across-calls-to-nfsd_cross_mnt Tue May 18 15:27:42 2004 +++ 25-akpm/fs/nfsd/nfs4xdr.c Tue May 18 15:27:42 2004 @@ -1686,6 +1686,7 @@ nfsd4_encode_dirent(struct readdir_cd *c goto error; } + exp_get(exp); if (d_mountpoint(dentry)) { if ((nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp))) { @@ -1697,6 +1698,7 @@ nfsd4_encode_dirent(struct readdir_cd *c * this call will be retried. */ dput(dentry); + exp_put(exp); nfserr = nfserr_dropit; goto error; } @@ -1707,6 +1709,7 @@ nfsd4_encode_dirent(struct readdir_cd *c dentry, p, &buflen, cd->rd_bmval, cd->rd_rqstp); dput(dentry); + exp_put(exp); if (!nfserr) { p += buflen; goto out; diff -puN fs/nfsd/vfs.c~knfsd-5-of-10-protect-reference-to-exp-across-calls-to-nfsd_cross_mnt fs/nfsd/vfs.c --- 25/fs/nfsd/vfs.c~knfsd-5-of-10-protect-reference-to-exp-across-calls-to-nfsd_cross_mnt Tue May 18 15:27:42 2004 +++ 25-akpm/fs/nfsd/vfs.c Tue May 18 15:27:42 2004 @@ -141,10 +141,11 @@ nfsd_lookup(struct svc_rqst *rqstp, stru /* Obtain dentry and export. */ err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC); if (err) - goto out; + return err; dparent = fhp->fh_dentry; exp = fhp->fh_export; + exp_get(exp); err = nfserr_acces; @@ -210,6 +211,7 @@ nfsd_lookup(struct svc_rqst *rqstp, stru err = nfserr_noent; dput(dentry); out: + exp_put(exp); return err; out_nfserr: diff -puN include/linux/nfsd/export.h~knfsd-5-of-10-protect-reference-to-exp-across-calls-to-nfsd_cross_mnt include/linux/nfsd/export.h --- 25/include/linux/nfsd/export.h~knfsd-5-of-10-protect-reference-to-exp-across-calls-to-nfsd_cross_mnt Tue May 18 15:27:42 2004 +++ 25-akpm/include/linux/nfsd/export.h Tue May 18 15:27:42 2004 @@ -110,6 +110,10 @@ static inline void exp_put(struct svc_ex svc_export_put(&exp->h, &svc_export_cache); } +static inline void exp_get(struct svc_export *exp) +{ + cache_get(&exp->h); +} static inline struct svc_export * exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) @@ -118,7 +122,7 @@ exp_find(struct auth_domain *clp, int fs if (ek && !IS_ERR(ek)) { struct svc_export *exp = ek->ek_export; int err; - cache_get(&exp->h); + exp_get(exp); expkey_put(&ek->h, &svc_expkey_cache); if (exp && (err = cache_check(&svc_export_cache, &exp->h, reqp))) _