[pnfs] [PATCH 09/11] Update xs_tcp_read_request() to handle back channel callbacks.

Benny Halevy bhalevy at panasas.com
Wed Nov 28 09:13:49 EST 2007


On Nov. 28, 2007, 6:25 +0200, ricardo.labiaga at netapp.com wrote:
> Traditionally NFS clients only expect RPC replies on the open connections.  With
> NFSv4.1, callbacks can arrive over an existing open connections.
> Update xs_tcp_read_request() to queue callback requests onto a queue where
> the callback service (a separate thread) is listening for the processing.
> Original code by Rahul Iyer (iyer at netapp.com).
> 
> Signed-off-by: Ricardo Labiaga <ricardo.labiaga at netapp.com>
> ---
>  net/sunrpc/xprtsock.c |   65 ++++++++++++++++++++++++++++++++++++++++---------
>  1 files changed, 53 insertions(+), 12 deletions(-)
> 
> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
> index 8347aac..0eda706 100644
> --- a/net/sunrpc/xprtsock.c
> +++ b/net/sunrpc/xprtsock.c
> @@ -35,6 +35,9 @@
>  #include <linux/sunrpc/svcsock.h>
>  #include <linux/sunrpc/xprtsock.h>
>  #include <linux/file.h>
> +#ifdef CONFIG_NFS_V4_1
> +#include <linux/sunrpc/bc_xprt.h>
> +#endif
>  
>  #include <net/sock.h>
>  #include <net/checksum.h>
> @@ -960,16 +963,34 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
>  	struct xdr_buf *rcvbuf;
>  	size_t len;
>  	ssize_t r;
> -
> -	/* Find and lock the request corresponding to this xid */
> -	spin_lock(&xprt->transport_lock);
> -	req = xprt_lookup_rqst(xprt, transport->tcp_xid);
> -	if (!req) {
> -		transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
> -		dprintk("RPC:       XID %08x request not found!\n",
> -				ntohl(transport->tcp_xid));
> -		spin_unlock(&xprt->transport_lock);
> -		return;
> +	u32 calldir;
> +
> +	calldir = ntohl(transport->tcp_calldir);
> +	if (calldir == RPC_REPLY) {
> +		/* Find and lock the request corresponding to this xid */
> +		spin_lock(&xprt->transport_lock);
> +		req = xprt_lookup_rqst(xprt, transport->tcp_xid);
> +		if (!req) {
> +			dprintk("RPC:       XID %08x request not found!\n",
> +					ntohl(transport->tcp_xid));
> +			goto error;
> +		}
> +	} else {
> +		/* RPC_CALL */
> +		if (xprt->bc_mempool) {
> +			req = xprt_alloc_bc_request(xprt);
> +		} else {
> +			dprintk("RPC:       Unexpected callback dropped\n");
> +			goto error;
> +		}
> +		if (req == NULL) {
> +			/*
> +			 * Drop the callback.
> +			 * XXX Should we instead terminate the connection?

you must disconnecting if you drop the request
yet I think we can so a better job with preallocating a request.
I'll send a proposal for that soonish...

Benny

> + 			 */
> +			dprintk("RPC:       Couldn't get rpc_rqst for the callback! Dropping callback...\n");
> +			goto error;
> +		}
>  	}
>  
>  	rcvbuf = &req->rq_private_buf;
> @@ -1026,10 +1047,30 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
>  	}
>  
>  out:
> -	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
> -		xprt_complete_rqst(req->rq_task, transport->tcp_copied);
> +	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
> +		if (calldir == RPC_REPLY) {
> +			xprt_complete_rqst(req->rq_task, transport->tcp_copied);
> +		} else {
> +			/*
> + 			 * Add callback request to callback list.  The callback
> + 			 * service sleeps on the sv_cb_waitq waiting for new
> + 			 * requests.  Wake it up after adding enqueing the
> + 			 * request.
> + 			 */
> +			spin_lock(&xprt->serv->sv_cb_lock);
> +			list_add(&req->rq_list, &xprt->serv->sv_cb_list);
> +			spin_unlock(&xprt->serv->sv_cb_lock);
> +			wake_up(&xprt->serv->sv_cb_waitq);
> +		}
> +	}
>  	spin_unlock(&xprt->transport_lock);

hrm, the lock isn't taken in the alldir != RPC_REPLY path

>  	xs_tcp_check_fraghdr(transport);
> +	return;
> +
> +error:
> +	transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
> +	spin_unlock(&xprt->transport_lock);

ditto

I'll send a patch to fix that

> +	return;
>  }
>  
>  static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)




More information about the pNFS mailing list