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

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
Loading
Loading
Loading
Loading
+23 −35
Original line number Diff line number Diff line
@@ -739,16 +739,18 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
	int err;
	
	if (!clp)
		return NULL;
		return ERR_PTR(-ENOENT);

	key.ek_client = clp;
	key.ek_fsidtype = fsid_type;
	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));

	ek = svc_expkey_lookup(&key);
	if (ek != NULL)
		if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
			ek = ERR_PTR(err);
	if (ek == NULL)
		return ERR_PTR(-ENOMEM);
	err = cache_check(&svc_expkey_cache, &ek->h, reqp);
	if (err)
		return ERR_PTR(err);
	return ek;
}

@@ -809,30 +811,21 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
		struct cache_req *reqp)
{
	struct svc_export *exp, key;
	int err;
	
	if (!clp)
		return NULL;
		return ERR_PTR(-ENOENT);

	key.ex_client = clp;
	key.ex_mnt = mnt;
	key.ex_dentry = dentry;

	exp = svc_export_lookup(&key);
	if (exp != NULL)  {
		int err;

	if (exp == NULL)
		return ERR_PTR(-ENOMEM);
	err = cache_check(&svc_export_cache, &exp->h, reqp);
		switch (err) {
		case 0: break;
		case -EAGAIN:
		case -ETIMEDOUT:
			exp = ERR_PTR(err);
			break;
		default:
			exp = NULL;
		}
	}

	if (err)
		return ERR_PTR(err);
	return exp;
}

@@ -848,7 +841,7 @@ exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
	dget(dentry);
	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;

		parent = dget_parent(dentry);
@@ -901,7 +894,7 @@ static void exp_fsid_unhash(struct svc_export *exp)
		return;

	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;
		cache_put(&ek->h, &svc_expkey_cache);
	}
@@ -939,7 +932,7 @@ static void exp_unhash(struct svc_export *exp)
	struct inode *inode = exp->ex_dentry->d_inode;

	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;
		cache_put(&ek->h, &svc_expkey_cache);
	}
@@ -990,13 +983,12 @@ exp_export(struct nfsctl_export *nxp)

	/* must make sure there won't be an ex_fsid clash */
	if ((nxp->ex_flags & NFSEXP_FSID) &&
	    (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
	    !IS_ERR(fsid_key) &&
	    (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
	    fsid_key->ek_mnt &&
	    (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
		goto finish;

	if (exp) {
	if (!IS_ERR(exp)) {
		/* just a flags/id/fsid update */

		exp_fsid_unhash(exp);
@@ -1105,7 +1097,7 @@ exp_unexport(struct nfsctl_export *nxp)
	err = -EINVAL;
	exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
	path_release(&nd);
	if (!exp)
	if (IS_ERR(exp))
		goto out_domain;

	exp_do_unexport(exp);
@@ -1150,10 +1142,6 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
		err = PTR_ERR(exp);
		goto out;
	}
	if (!exp) {
		dprintk("nfsd: exp_rootfh export not found.\n");
		goto out;
	}

	/*
	 * fh must be initialized before calling fh_compose
@@ -1177,13 +1165,13 @@ exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
{
	struct svc_export *exp;
	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));

	exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp);
	cache_put(&ek->h, &svc_expkey_cache);

	if (!exp || IS_ERR(exp))
	if (IS_ERR(exp))
		return ERR_PTR(PTR_ERR(exp));
	return exp;
}
@@ -1205,10 +1193,10 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);

	exp = exp_find(clp, FSID_NUM, fsidv, creq);
	if (PTR_ERR(exp) == -ENOENT)
		return nfserr_perm;
	if (IS_ERR(exp))
		return nfserrno(PTR_ERR(exp));
	if (exp == NULL)
		return nfserr_perm;
	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
	exp_put(exp);
	return rv;
+5 −6
Original line number Diff line number Diff line
@@ -160,15 +160,14 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
				       &rqstp->rq_chandle);
		}

		if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
				|| PTR_ERR(exp) == -ETIMEDOUT)) {
			error = nfserrno(PTR_ERR(exp));
		error = nfserr_stale;
		if (PTR_ERR(exp) == -ENOENT)
			goto out;
		}

		error = nfserr_stale; 
		if (!exp || IS_ERR(exp))
		if (IS_ERR(exp)) {
			error = nfserrno(PTR_ERR(exp));
			goto out;
		}

		/* Check if the request originated from a secure port. */
		error = nfserr_perm;
+4 −5
Original line number Diff line number Diff line
@@ -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,
					  &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);
				dput(dentry);
				mntput(mnt);
				goto out_nfserr;
			}
			if (!exp2) {
				dput(dentry);
				dentry = dget(dparent);
			} else {
				exp_put(exp);
				exp = exp2;