[pnfs] [PATCH 11/19] nfs41: Refactor svc_process()

J. Bruce Fields bfields at fieldses.org
Wed Jul 16 12:53:24 EDT 2008


On Wed, Jul 16, 2008 at 12:29:45PM +0300, Benny Halevy wrote:
> From: Ricardo Labiaga <ricardo.labiaga at netapp.com>
> 
> net/sunrpc/svc.c:svc_process() is used by the NFSv4 callback service
> to process RPC requests arriving over connections initiated by the
> server.  NFSv4.1 supports callbacks over the backchannel on connections
> initiated by the client.  This patch refactors svc_process() so that
> common code can also be used by the backchannel.
> 
> Signed-off-by: Ricardo Labiaga <ricardo.labiaga at netapp.com>
> Signed-off-by: Benny Halevy <bhalevy at panasas.com>
> ---
>  net/sunrpc/svc.c |   80 +++++++++++++++++++++++++++++++++--------------------
>  1 files changed, 50 insertions(+), 30 deletions(-)
> 
> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
> index 01c7e31..ef03377 100644
> --- a/net/sunrpc/svc.c
> +++ b/net/sunrpc/svc.c
> @@ -824,20 +824,18 @@ svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
>  }
>  
>  /*
> - * Process the RPC request.
> + * Common routine for processing the RPC request.
>   */
> -int
> -svc_process(struct svc_rqst *rqstp)
> +static int
> +svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
>  {
>  	struct svc_program	*progp;
>  	struct svc_version	*versp = NULL;	/* compiler food */
>  	struct svc_procedure	*procp = NULL;
> -	struct kvec *		argv = &rqstp->rq_arg.head[0];
> -	struct kvec *		resv = &rqstp->rq_res.head[0];
>  	struct svc_serv		*serv = rqstp->rq_server;
>  	kxdrproc_t		xdr;
>  	__be32			*statp;
> -	u32			dir, prog, vers, proc;
> +	u32			prog, vers, proc;
>  	__be32			auth_stat, rpc_stat;
>  	int			auth_res;
>  	__be32			*reply_statp;
> @@ -847,36 +845,19 @@ svc_process(struct svc_rqst *rqstp)
>  	if (argv->iov_len < 6*4)
>  		goto err_short_len;
>  
> -	/* setup response xdr_buf.
> -	 * Initially it has just one page
> -	 */
> -	rqstp->rq_resused = 1;
> -	resv->iov_base = page_address(rqstp->rq_respages[0]);
> -	resv->iov_len = 0;
> -	rqstp->rq_res.pages = rqstp->rq_respages + 1;
> -	rqstp->rq_res.len = 0;
> -	rqstp->rq_res.page_base = 0;
> -	rqstp->rq_res.page_len = 0;
> -	rqstp->rq_res.buflen = PAGE_SIZE;
> -	rqstp->rq_res.tail[0].iov_base = NULL;
> -	rqstp->rq_res.tail[0].iov_len = 0;
>  	/* Will be turned off only in gss privacy case: */
>  	rqstp->rq_splice_ok = 1;
>  
>  	/* Setup reply header */
>  	rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp);
>  
> -	rqstp->rq_xid = svc_getu32(argv);
>  	svc_putu32(resv, rqstp->rq_xid);
>  
> -	dir  = svc_getnl(argv);
>  	vers = svc_getnl(argv);
>  
>  	/* First words of reply: */
>  	svc_putnl(resv, 1);		/* REPLY */
>  
> -	if (dir != 0)		/* direction != CALL */
> -		goto err_bad_dir;
>  	if (vers != 2)		/* RPC version number */
>  		goto err_bad_rpc;
>  
> @@ -1000,7 +981,7 @@ svc_process(struct svc_rqst *rqstp)
>   sendit:
>  	if (svc_authorise(rqstp))
>  		goto dropit;
> -	return svc_send(rqstp);
> +	return 1;		/* Caller can now send it */
>  
>   dropit:
>  	svc_authorise(rqstp);	/* doesn't hurt to call this twice */
> @@ -1014,12 +995,6 @@ err_short_len:
>  
>  	goto dropit;			/* drop request */
>  
> -err_bad_dir:
> -	svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
> -
> -	serv->sv_stats->rpcbadfmt++;
> -	goto dropit;			/* drop request */
> -
>  err_bad_rpc:
>  	serv->sv_stats->rpcbadfmt++;
>  	svc_putnl(resv, 1);	/* REJECT */
> @@ -1073,6 +1048,51 @@ err_bad:
>  EXPORT_SYMBOL(svc_process);
>  
>  /*
> + * Process the RPC request.
> + */
> +int
> +svc_process(struct svc_rqst *rqstp)
> +{
> +	struct kvec		*argv = &rqstp->rq_arg.head[0];
> +	struct kvec		*resv = &rqstp->rq_res.head[0];
> +	struct svc_serv		*serv = rqstp->rq_server;
> +	u32			dir;
> +	int			error;
> +
> +	/*
> +	 * Setup response xdr_buf.
> +	 * Initially it has just one page
> +	 */
> +	rqstp->rq_resused = 1;
> +	resv->iov_base = page_address(rqstp->rq_respages[0]);
> +	resv->iov_len = 0;
> +	rqstp->rq_res.pages = rqstp->rq_respages + 1;
> +	rqstp->rq_res.len = 0;
> +	rqstp->rq_res.page_base = 0;
> +	rqstp->rq_res.page_len = 0;
> +	rqstp->rq_res.buflen = PAGE_SIZE;
> +	rqstp->rq_res.tail[0].iov_base = NULL;
> +	rqstp->rq_res.tail[0].iov_len = 0;
> +
> +	rqstp->rq_xid = svc_getu32(argv);
> +
> +	dir  = svc_getnl(argv);
> +	if (dir != 0) {
> +		/* direction != CALL */
> +		svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
> +		serv->sv_stats->rpcbadfmt++;
> +		svc_drop(rqstp);
> +		return 0;
> +	}
> +
> +	error = svc_process_common(rqstp, argv, resv);
> +	if (error <= 0)
> +		return error;
> +
> +	return svc_send(rqstp);
> +}

So the return value here is:
	- -ERRNO or 0 if already dropped
	- 1 to send

Could we do the svc_send() inside svc_process_common()?  If not, let's
at least add a quick sentence to the comment on svc_process_comment()
documenting the convention.

Non-standard conventions for return values seem to be an occasional
cause of bugs, so I've got a slight phobia.

--b.


More information about the pNFS mailing list