Commit 85085aac authored by Chuck Lever's avatar Chuck Lever Committed by J. Bruce Fields
Browse files

NFSD: Refactor nfsd_dispatch() error paths



nfsd_dispatch() is a hot path. Ensure the compiler takes the
processing of rare error cases out of line.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 4c96cb56
Loading
Loading
Loading
Loading
+35 −25
Original line number Diff line number Diff line
@@ -1021,29 +1021,24 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
	dprintk("nfsd_dispatch: vers %d proc %d\n",
				rqstp->rq_vers, rqstp->rq_proc);

	if (nfs_request_too_big(rqstp, proc)) {
		dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
		*statp = rpc_garbage_args;
		return 1;
	}
	if (nfs_request_too_big(rqstp, proc))
		goto out_too_large;

	/*
	 * Give the xdr decoder a chance to change this if it wants
	 * (necessary in the NFSv4.0 compound case)
	 */
	rqstp->rq_cachetype = proc->pc_cachetype;
	if (!proc->pc_decode(rqstp, argv->iov_base)) {
		dprintk("nfsd: failed to decode arguments!\n");
		*statp = rpc_garbage_args;
		return 1;
	}
	if (!proc->pc_decode(rqstp, argv->iov_base))
		goto out_decode_err;

	switch (nfsd_cache_lookup(rqstp)) {
	case RC_DOIT:
		break;
	case RC_REPLY:
		return 1;
		goto out_cached_reply;
	case RC_DROPIT:
		return 0;
		goto out_dropit;
	}

	/*
@@ -1055,11 +1050,8 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)

	nfserr = proc->pc_func(rqstp);
	nfserr = map_new_errors(rqstp->rq_vers, nfserr);
	if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) {
		dprintk("nfsd: Dropping request; may be revisited later\n");
		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
		return 0;
	}
	if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags))
		goto out_update_drop;

	if (rqstp->rq_proc != 0)
		*nfserrp++ = nfserr;
@@ -1067,18 +1059,36 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
	/*
	 * For NFSv2, additional info is never returned in case of an error.
	 */
	if (!(nfserr && rqstp->rq_vers == 2)) {
		if (!proc->pc_encode(rqstp, nfserrp)) {
	if (!(nfserr && rqstp->rq_vers == 2))
		if (!proc->pc_encode(rqstp, nfserrp))
			goto out_encode_err;

	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
out_cached_reply:
	return 1;

out_too_large:
	dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
	*statp = rpc_garbage_args;
	return 1;

out_decode_err:
	dprintk("nfsd: failed to decode arguments!\n");
	*statp = rpc_garbage_args;
	return 1;

out_update_drop:
	dprintk("nfsd: Dropping request; may be revisited later\n");
	nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
out_dropit:
	return 0;

out_encode_err:
	dprintk("nfsd: failed to encode result!\n");
	nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
	*statp = rpc_system_err;
	return 1;
}
	}

	nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
	return 1;
}

int nfsd_pool_stats_open(struct inode *inode, struct file *file)
{