Commit a1de7361 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] kNFSd: Change fh_compose to NOT consume a reference to the dentry.

From: NeilBrown <neilb@cse.unsw.edu.au>

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.
parent 4fc69688
......@@ -899,7 +899,7 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
* 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, struct svc_fh *fhp,
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);
......
......@@ -799,6 +799,7 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
{
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 *cd, struct svc_fh *fhp,
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;
}
/*
......
......@@ -1706,6 +1706,7 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
nfserr = nfsd4_encode_fattr(NULL, exp,
dentry, p, &buflen, cd->rd_bmval,
cd->rd_rqstp);
dput(dentry);
if (!nfserr) {
p += buflen;
goto out;
......
......@@ -367,7 +367,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
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);
......
......@@ -212,6 +212,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
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;
......
......@@ -208,6 +208,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
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, struct svc_fh *fhp,
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, struct svc_fh *fhp,
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, struct svc_fh *fhp,
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, struct svc_fh *fhp,
out:
fh_unlock(fhp);
if (dchild && !IS_ERR(dchild))
dput(dchild);
return err;
out_nfserr:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment