Commit 940e3318 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] SUNRPC: don't reencode when looping in call transmit.

If the call to xprt_transmit() fails due to socket buffer space
exhaustion, we do not need to re-encode the RPC message when we
loop back through call_transmit.

Re-encoding can actually end up triggering the WARN_ON() in
call_decode() if we re-encode something like a read() request and
auth->au_rslack has changed.
It can also cause us to increment the RPCSEC_GSS sequence number
beyond the limits of the allowed window.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e4d76e1c
...@@ -55,6 +55,7 @@ static void call_bind(struct rpc_task *task); ...@@ -55,6 +55,7 @@ static void call_bind(struct rpc_task *task);
static void call_bind_status(struct rpc_task *task); static void call_bind_status(struct rpc_task *task);
static void call_transmit(struct rpc_task *task); static void call_transmit(struct rpc_task *task);
static void call_status(struct rpc_task *task); static void call_status(struct rpc_task *task);
static void call_transmit_status(struct rpc_task *task);
static void call_refresh(struct rpc_task *task); static void call_refresh(struct rpc_task *task);
static void call_refreshresult(struct rpc_task *task); static void call_refreshresult(struct rpc_task *task);
static void call_timeout(struct rpc_task *task); static void call_timeout(struct rpc_task *task);
...@@ -672,6 +673,18 @@ call_allocate(struct rpc_task *task) ...@@ -672,6 +673,18 @@ call_allocate(struct rpc_task *task)
rpc_exit(task, -ERESTARTSYS); rpc_exit(task, -ERESTARTSYS);
} }
static inline int
rpc_task_need_encode(struct rpc_task *task)
{
return task->tk_rqstp->rq_snd_buf.len == 0;
}
static inline void
rpc_task_force_reencode(struct rpc_task *task)
{
task->tk_rqstp->rq_snd_buf.len = 0;
}
/* /*
* 3. Encode arguments of an RPC call * 3. Encode arguments of an RPC call
*/ */
...@@ -867,12 +880,14 @@ call_transmit(struct rpc_task *task) ...@@ -867,12 +880,14 @@ call_transmit(struct rpc_task *task)
if (task->tk_status != 0) if (task->tk_status != 0)
return; return;
/* Encode here so that rpcsec_gss can use correct sequence number. */ /* Encode here so that rpcsec_gss can use correct sequence number. */
if (task->tk_rqstp->rq_bytes_sent == 0) { if (rpc_task_need_encode(task)) {
task->tk_rqstp->rq_bytes_sent = 0;
call_encode(task); call_encode(task);
/* Did the encode result in an error condition? */ /* Did the encode result in an error condition? */
if (task->tk_status != 0) if (task->tk_status != 0)
goto out_nosend; goto out_nosend;
} }
task->tk_action = call_transmit_status;
xprt_transmit(task); xprt_transmit(task);
if (task->tk_status < 0) if (task->tk_status < 0)
return; return;
...@@ -884,6 +899,7 @@ call_transmit(struct rpc_task *task) ...@@ -884,6 +899,7 @@ call_transmit(struct rpc_task *task)
out_nosend: out_nosend:
/* release socket write lock before attempting to handle error */ /* release socket write lock before attempting to handle error */
xprt_abort_transmit(task); xprt_abort_transmit(task);
rpc_task_force_reencode(task);
} }
/* /*
...@@ -915,7 +931,6 @@ call_status(struct rpc_task *task) ...@@ -915,7 +931,6 @@ call_status(struct rpc_task *task)
break; break;
case -ECONNREFUSED: case -ECONNREFUSED:
case -ENOTCONN: case -ENOTCONN:
req->rq_bytes_sent = 0;
if (clnt->cl_autobind) if (clnt->cl_autobind)
clnt->cl_port = 0; clnt->cl_port = 0;
task->tk_action = call_bind; task->tk_action = call_bind;
...@@ -937,7 +952,18 @@ call_status(struct rpc_task *task) ...@@ -937,7 +952,18 @@ call_status(struct rpc_task *task)
} }
/* /*
* 6a. Handle RPC timeout * 6a. Handle transmission errors.
*/
static void
call_transmit_status(struct rpc_task *task)
{
if (task->tk_status != -EAGAIN)
rpc_task_force_reencode(task);
call_status(task);
}
/*
* 6b. Handle RPC timeout
* We do not release the request slot, so we keep using the * We do not release the request slot, so we keep using the
* same XID for all retransmits. * same XID for all retransmits.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment