Commit 2d3bb252 authored by J. Bruce Fields's avatar J. Bruce Fields Committed by Linus Torvalds

knfsd: nfsd: make all exp_finding functions return -errno's on err

Currently exp_find(), exp_get_by_name(), and friends, return an export on
success, and on failure return:

	errors -EAGAIN (drop this request pending an upcall) or
		-ETIMEDOUT (an upcall has timed out), or
	return NULL, which can mean either that there was a memory allocation
		failure, or that an export was not found, or that a passed-in
		export lacks an auth_domain.

Many callers seem to assume that NULL means that an export was not found,
which may lead to bugs in the case of a memory allocation failure.

Modify these functions to distinguish between the two NULL cases by returning
either -ENOENT or -ENOMEM.  They now never return NULL.  We get to simplify
some code in the process.

We return -ENOENT in the case of a missing auth_domain.  This case should
probably be removed (or converted to a bug) after confirming that it can never
happen.
Signed-off-by: default avatar"J. Bruce Fields" <bfields@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 47f9940c
...@@ -739,16 +739,18 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) ...@@ -739,16 +739,18 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
int err; int err;
if (!clp) if (!clp)
return NULL; return ERR_PTR(-ENOENT);
key.ek_client = clp; key.ek_client = clp;
key.ek_fsidtype = fsid_type; key.ek_fsidtype = fsid_type;
memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
ek = svc_expkey_lookup(&key); ek = svc_expkey_lookup(&key);
if (ek != NULL) if (ek == NULL)
if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) return ERR_PTR(-ENOMEM);
ek = ERR_PTR(err); err = cache_check(&svc_expkey_cache, &ek->h, reqp);
if (err)
return ERR_PTR(err);
return ek; return ek;
} }
...@@ -809,30 +811,21 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, ...@@ -809,30 +811,21 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
struct cache_req *reqp) struct cache_req *reqp)
{ {
struct svc_export *exp, key; struct svc_export *exp, key;
int err;
if (!clp) if (!clp)
return NULL; return ERR_PTR(-ENOENT);
key.ex_client = clp; key.ex_client = clp;
key.ex_mnt = mnt; key.ex_mnt = mnt;
key.ex_dentry = dentry; key.ex_dentry = dentry;
exp = svc_export_lookup(&key); exp = svc_export_lookup(&key);
if (exp != NULL) { if (exp == NULL)
int err; return ERR_PTR(-ENOMEM);
err = cache_check(&svc_export_cache, &exp->h, reqp); err = cache_check(&svc_export_cache, &exp->h, reqp);
switch (err) { if (err)
case 0: break; return ERR_PTR(err);
case -EAGAIN:
case -ETIMEDOUT:
exp = ERR_PTR(err);
break;
default:
exp = NULL;
}
}
return exp; return exp;
} }
...@@ -848,7 +841,7 @@ exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, ...@@ -848,7 +841,7 @@ exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
dget(dentry); dget(dentry);
exp = exp_get_by_name(clp, mnt, dentry, reqp); exp = exp_get_by_name(clp, mnt, dentry, reqp);
while (exp == NULL && !IS_ROOT(dentry)) { while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(dentry)) {
struct dentry *parent; struct dentry *parent;
parent = dget_parent(dentry); parent = dget_parent(dentry);
...@@ -901,7 +894,7 @@ static void exp_fsid_unhash(struct svc_export *exp) ...@@ -901,7 +894,7 @@ static void exp_fsid_unhash(struct svc_export *exp)
return; return;
ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
if (ek && !IS_ERR(ek)) { if (!IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1; ek->h.expiry_time = get_seconds()-1;
cache_put(&ek->h, &svc_expkey_cache); cache_put(&ek->h, &svc_expkey_cache);
} }
...@@ -939,7 +932,7 @@ static void exp_unhash(struct svc_export *exp) ...@@ -939,7 +932,7 @@ static void exp_unhash(struct svc_export *exp)
struct inode *inode = exp->ex_dentry->d_inode; struct inode *inode = exp->ex_dentry->d_inode;
ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
if (ek && !IS_ERR(ek)) { if (!IS_ERR(ek)) {
ek->h.expiry_time = get_seconds()-1; ek->h.expiry_time = get_seconds()-1;
cache_put(&ek->h, &svc_expkey_cache); cache_put(&ek->h, &svc_expkey_cache);
} }
...@@ -990,13 +983,12 @@ exp_export(struct nfsctl_export *nxp) ...@@ -990,13 +983,12 @@ exp_export(struct nfsctl_export *nxp)
/* must make sure there won't be an ex_fsid clash */ /* must make sure there won't be an ex_fsid clash */
if ((nxp->ex_flags & NFSEXP_FSID) && if ((nxp->ex_flags & NFSEXP_FSID) &&
(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
!IS_ERR(fsid_key) &&
fsid_key->ek_mnt && fsid_key->ek_mnt &&
(fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
goto finish; goto finish;
if (exp) { if (!IS_ERR(exp)) {
/* just a flags/id/fsid update */ /* just a flags/id/fsid update */
exp_fsid_unhash(exp); exp_fsid_unhash(exp);
...@@ -1105,7 +1097,7 @@ exp_unexport(struct nfsctl_export *nxp) ...@@ -1105,7 +1097,7 @@ exp_unexport(struct nfsctl_export *nxp)
err = -EINVAL; err = -EINVAL;
exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
path_release(&nd); path_release(&nd);
if (!exp) if (IS_ERR(exp))
goto out_domain; goto out_domain;
exp_do_unexport(exp); exp_do_unexport(exp);
...@@ -1150,10 +1142,6 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) ...@@ -1150,10 +1142,6 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
err = PTR_ERR(exp); err = PTR_ERR(exp);
goto out; goto out;
} }
if (!exp) {
dprintk("nfsd: exp_rootfh export not found.\n");
goto out;
}
/* /*
* fh must be initialized before calling fh_compose * fh must be initialized before calling fh_compose
...@@ -1177,13 +1165,13 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, ...@@ -1177,13 +1165,13 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
{ {
struct svc_export *exp; struct svc_export *exp;
struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp);
if (!ek || IS_ERR(ek)) if (IS_ERR(ek))
return ERR_PTR(PTR_ERR(ek)); return ERR_PTR(PTR_ERR(ek));
exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
cache_put(&ek->h, &svc_expkey_cache); cache_put(&ek->h, &svc_expkey_cache);
if (!exp || IS_ERR(exp)) if (IS_ERR(exp))
return ERR_PTR(PTR_ERR(exp)); return ERR_PTR(PTR_ERR(exp));
return exp; return exp;
} }
...@@ -1205,10 +1193,10 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, ...@@ -1205,10 +1193,10 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
exp = exp_find(clp, FSID_NUM, fsidv, creq); exp = exp_find(clp, FSID_NUM, fsidv, creq);
if (PTR_ERR(exp) == -ENOENT)
return nfserr_perm;
if (IS_ERR(exp)) if (IS_ERR(exp))
return nfserrno(PTR_ERR(exp)); return nfserrno(PTR_ERR(exp));
if (exp == NULL)
return nfserr_perm;
rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
exp_put(exp); exp_put(exp);
return rv; return rv;
......
...@@ -160,15 +160,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -160,15 +160,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
&rqstp->rq_chandle); &rqstp->rq_chandle);
} }
if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN error = nfserr_stale;
|| PTR_ERR(exp) == -ETIMEDOUT)) { if (PTR_ERR(exp) == -ENOENT)
error = nfserrno(PTR_ERR(exp));
goto out; goto out;
}
error = nfserr_stale; if (IS_ERR(exp)) {
if (!exp || IS_ERR(exp)) error = nfserrno(PTR_ERR(exp));
goto out; goto out;
}
/* Check if the request originated from a secure port. */ /* Check if the request originated from a secure port. */
error = nfserr_perm; error = nfserr_perm;
......
...@@ -192,15 +192,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, ...@@ -192,15 +192,14 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
exp2 = exp_parent(exp->ex_client, mnt, dentry, exp2 = exp_parent(exp->ex_client, mnt, dentry,
&rqstp->rq_chandle); &rqstp->rq_chandle);
if (IS_ERR(exp2)) { if (PTR_ERR(exp2) == -ENOENT) {
dput(dentry);
dentry = dget(dparent);
} else if (IS_ERR(exp2)) {
host_err = PTR_ERR(exp2); host_err = PTR_ERR(exp2);
dput(dentry); dput(dentry);
mntput(mnt); mntput(mnt);
goto out_nfserr; goto out_nfserr;
}
if (!exp2) {
dput(dentry);
dentry = dget(dparent);
} else { } else {
exp_put(exp); exp_put(exp);
exp = exp2; exp = exp2;
......
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