diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
| -rw-r--r-- | net/sunrpc/clnt.c | 174 | 
1 files changed, 82 insertions, 92 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 8ea2f5fadd96..ae3b8145da35 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -61,6 +61,7 @@ static void	call_start(struct rpc_task *task);  static void	call_reserve(struct rpc_task *task);  static void	call_reserveresult(struct rpc_task *task);  static void	call_allocate(struct rpc_task *task); +static void	call_encode(struct rpc_task *task);  static void	call_decode(struct rpc_task *task);  static void	call_bind(struct rpc_task *task);  static void	call_bind_status(struct rpc_task *task); @@ -1137,10 +1138,10 @@ EXPORT_SYMBOL_GPL(rpc_call_async);  struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req)  {  	struct rpc_task *task; -	struct xdr_buf *xbufp = &req->rq_snd_buf;  	struct rpc_task_setup task_setup_data = {  		.callback_ops = &rpc_default_ops, -		.flags = RPC_TASK_SOFTCONN, +		.flags = RPC_TASK_SOFTCONN | +			RPC_TASK_NO_RETRANS_TIMEOUT,  	};  	dprintk("RPC: rpc_run_bc_task req= %p\n", req); @@ -1148,14 +1149,7 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req)  	 * Create an rpc_task to send the data  	 */  	task = rpc_new_task(&task_setup_data); -	task->tk_rqstp = req; - -	/* -	 * Set up the xdr_buf length. -	 * This also indicates that the buffer is XDR encoded already. -	 */ -	xbufp->len = xbufp->head[0].iov_len + xbufp->page_len + -			xbufp->tail[0].iov_len; +	xprt_init_bc_request(req, task);  	task->tk_action = call_bc_transmit;  	atomic_inc(&task->tk_count); @@ -1558,7 +1552,6 @@ call_reserveresult(struct rpc_task *task)  	task->tk_status = 0;  	if (status >= 0) {  		if (task->tk_rqstp) { -			xprt_request_init(task);  			task->tk_action = call_refresh;  			return;  		} @@ -1680,7 +1673,7 @@ call_allocate(struct rpc_task *task)  	dprint_status(task);  	task->tk_status = 0; -	task->tk_action = call_bind; +	task->tk_action = call_encode;  	if (req->rq_buffer)  		return; @@ -1721,22 +1714,15 @@ call_allocate(struct rpc_task *task)  	rpc_exit(task, -ERESTARTSYS);  } -static inline int +static int  rpc_task_need_encode(struct rpc_task *task)  { -	return task->tk_rqstp->rq_snd_buf.len == 0; +	return test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate) == 0 && +		(!(task->tk_flags & RPC_TASK_SENT) || +		 !(task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT) || +		 xprt_request_need_retransmit(task));  } -static inline void -rpc_task_force_reencode(struct rpc_task *task) -{ -	task->tk_rqstp->rq_snd_buf.len = 0; -	task->tk_rqstp->rq_bytes_sent = 0; -} - -/* - * 3.	Encode arguments of an RPC call - */  static void  rpc_xdr_encode(struct rpc_task *task)  { @@ -1752,6 +1738,7 @@ rpc_xdr_encode(struct rpc_task *task)  	xdr_buf_init(&req->rq_rcv_buf,  		     req->rq_rbuffer,  		     req->rq_rcvsize); +	req->rq_bytes_sent = 0;  	p = rpc_encode_header(task);  	if (p == NULL) { @@ -1766,6 +1753,36 @@ rpc_xdr_encode(struct rpc_task *task)  	task->tk_status = rpcauth_wrap_req(task, encode, req, p,  			task->tk_msg.rpc_argp); +	if (task->tk_status == 0) +		xprt_request_prepare(req); +} + +/* + * 3.	Encode arguments of an RPC call + */ +static void +call_encode(struct rpc_task *task) +{ +	if (!rpc_task_need_encode(task)) +		goto out; +	/* Encode here so that rpcsec_gss can use correct sequence number. */ +	rpc_xdr_encode(task); +	/* Did the encode result in an error condition? */ +	if (task->tk_status != 0) { +		/* Was the error nonfatal? */ +		if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM) +			rpc_delay(task, HZ >> 4); +		else +			rpc_exit(task, task->tk_status); +		return; +	} + +	/* Add task to reply queue before transmission to avoid races */ +	if (rpc_reply_expected(task)) +		xprt_request_enqueue_receive(task); +	xprt_request_enqueue_transmit(task); +out: +	task->tk_action = call_bind;  }  /* @@ -1947,43 +1964,16 @@ call_connect_status(struct rpc_task *task)  static void  call_transmit(struct rpc_task *task)  { -	int is_retrans = RPC_WAS_SENT(task); -  	dprint_status(task); -	task->tk_action = call_status; -	if (task->tk_status < 0) -		return; -	if (!xprt_prepare_transmit(task)) -		return; -	task->tk_action = call_transmit_status; -	/* Encode here so that rpcsec_gss can use correct sequence number. */ -	if (rpc_task_need_encode(task)) { -		rpc_xdr_encode(task); -		/* Did the encode result in an error condition? */ -		if (task->tk_status != 0) { -			/* Was the error nonfatal? */ -			if (task->tk_status == -EAGAIN) -				rpc_delay(task, HZ >> 4); -			else -				rpc_exit(task, task->tk_status); +	task->tk_status = 0; +	if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) { +		if (!xprt_prepare_transmit(task))  			return; -		} +		xprt_transmit(task);  	} -	xprt_transmit(task); -	if (task->tk_status < 0) -		return; -	if (is_retrans) -		task->tk_client->cl_stats->rpcretrans++; -	/* -	 * On success, ensure that we call xprt_end_transmit() before sleeping -	 * in order to allow access to the socket to other RPC requests. -	 */ -	call_transmit_status(task); -	if (rpc_reply_expected(task)) -		return; -	task->tk_action = rpc_exit_task; -	rpc_wake_up_queued_task(&task->tk_rqstp->rq_xprt->pending, task); +	task->tk_action = call_transmit_status; +	xprt_end_transmit(task);  }  /* @@ -1999,19 +1989,17 @@ call_transmit_status(struct rpc_task *task)  	 * test first.  	 */  	if (task->tk_status == 0) { -		xprt_end_transmit(task); -		rpc_task_force_reencode(task); +		xprt_request_wait_receive(task);  		return;  	}  	switch (task->tk_status) { -	case -EAGAIN: -	case -ENOBUFS: -		break;  	default:  		dprint_status(task); -		xprt_end_transmit(task); -		rpc_task_force_reencode(task); +		break; +	case -EBADMSG: +		task->tk_status = 0; +		task->tk_action = call_encode;  		break;  		/*  		 * Special cases: if we've been waiting on the @@ -2019,6 +2007,14 @@ call_transmit_status(struct rpc_task *task)  		 * socket just returned a connection error,  		 * then hold onto the transport lock.  		 */ +	case -ENOBUFS: +		rpc_delay(task, HZ>>2); +		/* fall through */ +	case -EBADSLT: +	case -EAGAIN: +		task->tk_action = call_transmit; +		task->tk_status = 0; +		break;  	case -ECONNREFUSED:  	case -EHOSTDOWN:  	case -ENETDOWN: @@ -2026,7 +2022,6 @@ call_transmit_status(struct rpc_task *task)  	case -ENETUNREACH:  	case -EPERM:  		if (RPC_IS_SOFTCONN(task)) { -			xprt_end_transmit(task);  			if (!task->tk_msg.rpc_proc->p_proc)  				trace_xprt_ping(task->tk_xprt,  						task->tk_status); @@ -2039,7 +2034,7 @@ call_transmit_status(struct rpc_task *task)  	case -EADDRINUSE:  	case -ENOTCONN:  	case -EPIPE: -		rpc_task_force_reencode(task); +		break;  	}  } @@ -2053,6 +2048,11 @@ call_bc_transmit(struct rpc_task *task)  {  	struct rpc_rqst *req = task->tk_rqstp; +	if (rpc_task_need_encode(task)) +		xprt_request_enqueue_transmit(task); +	if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) +		goto out_wakeup; +  	if (!xprt_prepare_transmit(task))  		goto out_retry; @@ -2061,14 +2061,9 @@ call_bc_transmit(struct rpc_task *task)  			"error: %d\n", task->tk_status);  		goto out_done;  	} -	if (req->rq_connect_cookie != req->rq_xprt->connect_cookie) -		req->rq_bytes_sent = 0;  	xprt_transmit(task); -	if (task->tk_status == -EAGAIN) -		goto out_nospace; -  	xprt_end_transmit(task);  	dprint_status(task);  	switch (task->tk_status) { @@ -2084,6 +2079,8 @@ call_bc_transmit(struct rpc_task *task)  	case -ENOTCONN:  	case -EPIPE:  		break; +	case -EAGAIN: +		goto out_retry;  	case -ETIMEDOUT:  		/*  		 * Problem reaching the server.  Disconnect and let the @@ -2107,12 +2104,11 @@ call_bc_transmit(struct rpc_task *task)  			"error: %d\n", task->tk_status);  		break;  	} +out_wakeup:  	rpc_wake_up_queued_task(&req->rq_xprt->pending, task);  out_done:  	task->tk_action = rpc_exit_task;  	return; -out_nospace: -	req->rq_connect_cookie = req->rq_xprt->connect_cookie;  out_retry:  	task->tk_status = 0;  } @@ -2125,15 +2121,11 @@ static void  call_status(struct rpc_task *task)  {  	struct rpc_clnt	*clnt = task->tk_client; -	struct rpc_rqst	*req = task->tk_rqstp;  	int		status;  	if (!task->tk_msg.rpc_proc->p_proc)  		trace_xprt_ping(task->tk_xprt, task->tk_status); -	if (req->rq_reply_bytes_recvd > 0 && !req->rq_bytes_sent) -		task->tk_status = req->rq_reply_bytes_recvd; -  	dprint_status(task);  	status = task->tk_status; @@ -2173,13 +2165,8 @@ call_status(struct rpc_task *task)  		/* fall through */  	case -EPIPE:  	case -ENOTCONN: -		task->tk_action = call_bind; -		break; -	case -ENOBUFS: -		rpc_delay(task, HZ>>2); -		/* fall through */  	case -EAGAIN: -		task->tk_action = call_transmit; +		task->tk_action = call_encode;  		break;  	case -EIO:  		/* shutdown or soft timeout */ @@ -2244,7 +2231,7 @@ call_timeout(struct rpc_task *task)  	rpcauth_invalcred(task);  retry: -	task->tk_action = call_bind; +	task->tk_action = call_encode;  	task->tk_status = 0;  } @@ -2261,6 +2248,11 @@ call_decode(struct rpc_task *task)  	dprint_status(task); +	if (!decode) { +		task->tk_action = rpc_exit_task; +		return; +	} +  	if (task->tk_flags & RPC_CALL_MAJORSEEN) {  		if (clnt->cl_chatty) {  			printk(KERN_NOTICE "%s: server %s OK\n", @@ -2283,7 +2275,7 @@ call_decode(struct rpc_task *task)  	if (req->rq_rcv_buf.len < 12) {  		if (!RPC_IS_SOFT(task)) { -			task->tk_action = call_bind; +			task->tk_action = call_encode;  			goto out_retry;  		}  		dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n", @@ -2298,13 +2290,11 @@ call_decode(struct rpc_task *task)  			goto out_retry;  		return;  	} -  	task->tk_action = rpc_exit_task; -	if (decode) { -		task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, -						      task->tk_msg.rpc_resp); -	} +	task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, +					      task->tk_msg.rpc_resp); +  	dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,  			task->tk_status);  	return; @@ -2416,7 +2406,7 @@ rpc_verify_header(struct rpc_task *task)  			task->tk_garb_retry--;  			dprintk("RPC: %5u %s: retry garbled creds\n",  					task->tk_pid, __func__); -			task->tk_action = call_bind; +			task->tk_action = call_encode;  			goto out_retry;  		case RPC_AUTH_TOOWEAK:  			printk(KERN_NOTICE "RPC: server %s requires stronger " @@ -2485,7 +2475,7 @@ out_garbage:  		task->tk_garb_retry--;  		dprintk("RPC: %5u %s: retrying\n",  				task->tk_pid, __func__); -		task->tk_action = call_bind; +		task->tk_action = call_encode;  out_retry:  		return ERR_PTR(-EAGAIN);  	}  | 
