if (task->tk_status < 0)
return;
task->tk_status = xprt_prepare_transmit(task);
- if (task->tk_status < 0)
+ if (task->tk_status != 0)
return;
/* Encode here so that rpcsec_gss can use correct sequence number. */
if (!task->tk_rqstp->rq_bytes_sent)
struct rpc_rqst *req = task->tk_rqstp;
int status;
- if (req->rq_received != 0)
+ if (req->rq_received > 0 && !req->rq_bytes_sent)
task->tk_status = req->rq_received;
dprintk("RPC: %4d call_status (status %d)\n",
if (task->tk_status < 12) {
if (!clnt->cl_softrtry) {
- task->tk_action = call_transmit;
+ task->tk_action = call_bind;
clnt->cl_stats->rpcretrans++;
- } else {
- printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n",
- clnt->cl_protname, task->tk_status);
- rpc_exit(task, -EIO);
+ goto out_retry;
}
+ printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n",
+ clnt->cl_protname, task->tk_status);
+ rpc_exit(task, -EIO);
return;
}
/* Verify the RPC header */
- if (!(p = call_verify(task)))
- return;
+ if (!(p = call_verify(task))) {
+ if (task->tk_action == NULL)
+ return;
+ goto out_retry;
+ }
/*
* The following is an NFS-specific hack to cater for setuid
task->tk_flags ^= RPC_CALL_REALUID;
task->tk_action = call_bind;
task->tk_suid_retry--;
- return;
+ goto out_retry;
}
}
task->tk_status = decode(req, p, task->tk_msg.rpc_resp);
dprintk("RPC: %4d call_decode result %d\n", task->tk_pid,
task->tk_status);
+ return;
+out_retry:
+ req->rq_received = 0;
+ task->tk_status = 0;
}
/*
static int
__xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
{
+ struct rpc_rqst *req = task->tk_rqstp;
+
if (!xprt->snd_task) {
- if (xprt->nocong || __xprt_get_cong(xprt, task))
+ if (xprt->nocong || __xprt_get_cong(xprt, task)) {
xprt->snd_task = task;
+ if (req)
+ req->rq_bytes_sent = 0;
+ }
}
if (xprt->snd_task != task) {
dprintk("RPC: %4d TCP write queue full\n", task->tk_pid);
task->tk_timeout = 0;
task->tk_status = -EAGAIN;
- if (task->tk_rqstp && task->tk_rqstp->rq_nresend)
+ if (req && req->rq_nresend)
rpc_sleep_on(&xprt->resend, task, NULL, NULL);
else
rpc_sleep_on(&xprt->sending, task, NULL, NULL);
if (!task)
return;
}
- if (xprt->nocong || __xprt_get_cong(xprt, task))
+ if (xprt->nocong || __xprt_get_cong(xprt, task)) {
+ struct rpc_rqst *req = task->tk_rqstp;
xprt->snd_task = task;
+ if (req)
+ req->rq_bytes_sent = 0;
+ }
}
/*
if (xprt_connected(xprt))
goto out_write;
+ if (task->tk_rqstp)
+ task->tk_rqstp->rq_bytes_sent = 0;
+
/*
* We're here because the xprt was marked disconnected.
* Start by resetting any existing state.
if (xprt->shutdown)
return -EIO;
- if (task->tk_rpcwait)
- rpc_remove_wait_queue(task);
-
spin_lock_bh(&xprt->sock_lock);
+ if (req->rq_received && !req->rq_bytes_sent) {
+ err = req->rq_received;
+ goto out_unlock;
+ }
if (!__xprt_lock_write(xprt, task)) {
err = -EAGAIN;
goto out_unlock;
if (xprt->stream) {
req->rq_bytes_sent += status;
- if (req->rq_bytes_sent >= req->rq_slen)
+ /* If we've sent the entire packet, immediately
+ * reset the count of bytes sent. */
+ if (req->rq_bytes_sent >= req->rq_slen) {
+ req->rq_bytes_sent = 0;
goto out_receive;
+ }
} else {
if (status >= req->rq_slen)
goto out_receive;
* hence there is no danger of the waking up task being put on
* schedq, and being picked up by a parallel run of rpciod().
*/
- if (req->rq_received)
- goto out_release;
-
task->tk_status = status;
switch (status) {
if (xprt->stream)
xprt_disconnect(xprt);
}
- out_release:
xprt_release_write(xprt, task);
- req->rq_bytes_sent = 0;
return;
out_receive:
dprintk("RPC: %4d xmit complete\n", task->tk_pid);
/* Set the task's receive timeout value */
+ spin_lock_bh(&xprt->sock_lock);
if (!xprt->nocong) {
task->tk_timeout = rpc_calc_rto(&clnt->cl_rtt,
task->tk_msg.rpc_proc->p_timer);
task->tk_timeout = req->rq_timeout.to_maxval;
} else
task->tk_timeout = req->rq_timeout.to_current;
- spin_lock_bh(&xprt->sock_lock);
/* Don't race with disconnect */
if (!xprt_connected(xprt))
task->tk_status = -ENOTCONN;
rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
__xprt_release_write(xprt, task);
spin_unlock_bh(&xprt->sock_lock);
- req->rq_bytes_sent = 0;
}
/*