From: NeilBrown fh_compose currently consumes a reference to the dentry but not the export point. This is both inconsistent and confusing. It is better if a routine like this doesn't consume reference points, so with this patch, it doesn't. This fixes a couple of very subtle and unusual reference counting errors. --- 25-akpm/fs/nfsd/export.c | 3 +-- 25-akpm/fs/nfsd/nfs3xdr.c | 12 +++++++----- 25-akpm/fs/nfsd/nfs4xdr.c | 1 + 25-akpm/fs/nfsd/nfsfh.c | 2 +- 25-akpm/fs/nfsd/nfsproc.c | 1 + 25-akpm/fs/nfsd/vfs.c | 9 +++++++-- 6 files changed, 18 insertions(+), 10 deletions(-) diff -puN fs/nfsd/export.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry fs/nfsd/export.c --- 25/fs/nfsd/export.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry Tue May 18 15:27:41 2004 +++ 25-akpm/fs/nfsd/export.c Tue May 18 15:27:41 2004 @@ -899,7 +899,7 @@ exp_rootfh(svc_client *clp, char *path, * fh must be initialized before calling fh_compose */ fh_init(&fh, maxsize); - if (fh_compose(&fh, exp, dget(nd.dentry), NULL)) + if (fh_compose(&fh, exp, nd.dentry, NULL)) err = -EINVAL; else err = 0; @@ -932,7 +932,6 @@ exp_pseudoroot(struct auth_domain *clp, if (!fsid_key || IS_ERR(fsid_key)) return nfserr_perm; - dget(fsid_key->ek_export->ex_dentry); rv = fh_compose(fhp, fsid_key->ek_export, fsid_key->ek_export->ex_dentry, NULL); expkey_put(&fsid_key->h, &svc_expkey_cache); diff -puN fs/nfsd/nfs3xdr.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry fs/nfsd/nfs3xdr.c --- 25/fs/nfsd/nfs3xdr.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry Tue May 18 15:27:41 2004 +++ 25-akpm/fs/nfsd/nfs3xdr.c Tue May 18 15:27:41 2004 @@ -799,6 +799,7 @@ compose_entry_fh(struct nfsd3_readdirres { struct svc_export *exp; struct dentry *dparent, *dchild; + int rv = 0; dparent = cd->fh.fh_dentry; exp = cd->fh.fh_export; @@ -813,11 +814,12 @@ compose_entry_fh(struct nfsd3_readdirres dchild = lookup_one_len(name, dparent, namlen); if (IS_ERR(dchild)) return 1; - if (d_mountpoint(dchild)) - return 1; - if (fh_compose(fhp, exp, dchild, &cd->fh) != 0 || !dchild->d_inode) - return 1; - return 0; + if (d_mountpoint(dchild) || + fh_compose(fhp, exp, dchild, &cd->fh) != 0 || + !dchild->d_inode) + rv = 1; + dput(dchild); + return rv; } /* diff -puN fs/nfsd/nfs4xdr.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry fs/nfsd/nfs4xdr.c --- 25/fs/nfsd/nfs4xdr.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry Tue May 18 15:27:41 2004 +++ 25-akpm/fs/nfsd/nfs4xdr.c Tue May 18 15:27:41 2004 @@ -1706,6 +1706,7 @@ nfsd4_encode_dirent(struct readdir_cd *c nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, &buflen, cd->rd_bmval, cd->rd_rqstp); + dput(dentry); if (!nfserr) { p += buflen; goto out; diff -puN fs/nfsd/nfsfh.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry fs/nfsd/nfsfh.c --- 25/fs/nfsd/nfsfh.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry Tue May 18 15:27:41 2004 +++ 25-akpm/fs/nfsd/nfsfh.c Tue May 18 15:27:41 2004 @@ -367,7 +367,7 @@ fh_compose(struct svc_fh *fhp, struct sv printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); - fhp->fh_dentry = dentry; /* our internal copy */ + fhp->fh_dentry = dget(dentry); /* our internal copy */ fhp->fh_export = exp; cache_get(&exp->h); diff -puN fs/nfsd/nfsproc.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry fs/nfsd/nfsproc.c --- 25/fs/nfsd/nfsproc.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry Tue May 18 15:27:41 2004 +++ 25-akpm/fs/nfsd/nfsproc.c Tue May 18 15:27:41 2004 @@ -212,6 +212,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp); if (!nfserr && !dchild->d_inode) nfserr = nfserr_noent; + dput(dchild); if (nfserr) { if (nfserr != nfserr_noent) goto out_unlock; diff -puN fs/nfsd/vfs.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry fs/nfsd/vfs.c --- 25/fs/nfsd/vfs.c~knfsd-4-of-10-change-fh_compose-to-not-consume-a-reference-to-the-dentry Tue May 18 15:27:41 2004 +++ 25-akpm/fs/nfsd/vfs.c Tue May 18 15:27:41 2004 @@ -208,6 +208,7 @@ nfsd_lookup(struct svc_rqst *rqstp, stru err = fh_compose(resfh, exp, dentry, fhp); if (!err && !dentry->d_inode) err = nfserr_noent; + dput(dentry); out: return err; @@ -859,7 +860,7 @@ nfsd_create(struct svc_rqst *rqstp, stru char *fname, int flen, struct iattr *iap, int type, dev_t rdev, struct svc_fh *resfhp) { - struct dentry *dentry, *dchild; + struct dentry *dentry, *dchild = NULL; struct inode *dirp; int err; @@ -965,6 +966,8 @@ nfsd_create(struct svc_rqst *rqstp, stru if (!err) err = fh_update(resfhp); out: + if (dchild && !IS_ERR(dchild)) + dput(dchild); return err; out_nfserr: @@ -982,7 +985,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s struct svc_fh *resfhp, int createmode, u32 *verifier, int *truncp) { - struct dentry *dentry, *dchild; + struct dentry *dentry, *dchild = NULL; struct inode *dirp; int err; __u32 v_mtime=0, v_atime=0; @@ -1111,6 +1114,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s out: fh_unlock(fhp); + if (dchild && !IS_ERR(dchild)) + dput(dchild); return err; out_nfserr: _