unsigned long);
void xprt_reserve(struct rpc_task *);
+int xprt_prepare_transmit(struct rpc_task *);
void xprt_transmit(struct rpc_task *);
void xprt_receive(struct rpc_task *);
int xprt_adjust_timeout(struct rpc_timeout *);
dprintk("RPC: %4d call_allocate (status %d)\n",
task->tk_pid, task->tk_status);
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
if (task->tk_buffer)
return;
dprintk("RPC: %4d call_encode (status %d)\n",
task->tk_pid, task->tk_status);
- task->tk_action = call_bind;
-
/* Default buffer setup */
bufsiz = task->tk_bufsize >> 1;
sndbuf->head[0].iov_base = (void *)task->tk_buffer;
if (!(p = call_header(task))) {
printk(KERN_INFO "RPC: call_header failed, exit EIO\n");
rpc_exit(task, -EIO);
- } else
+ return;
+ }
if (encode && (status = encode(req, p, task->tk_msg.rpc_argp)) < 0) {
printk(KERN_WARNING "%s: can't encode arguments: %d\n",
clnt->cl_protname, -status);
task->tk_pid, task->tk_status);
task->tk_action = call_status;
+ if (task->tk_status < 0)
+ return;
+ task->tk_status = xprt_prepare_transmit(task);
+ if (task->tk_status < 0)
+ return;
+ /* Encode here so that rpcsec_gss can use correct sequence number. */
+ call_encode(task);
if (task->tk_status < 0)
return;
xprt_transmit(task);
- if (!task->tk_msg.rpc_proc->p_decode && task->tk_status >= 0) {
+ if (task->tk_status < 0)
+ return;
+ if (!task->tk_msg.rpc_proc->p_decode) {
task->tk_action = NULL;
rpc_wake_up_task(task);
}
if (RPC_IS_SETUID(task) && task->tk_suid_retry) {
dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
task->tk_flags ^= RPC_CALL_REALUID;
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
task->tk_suid_retry--;
return;
}
task->tk_garb_retry--;
dprintk("RPC: %4d call_verify: retry garbled creds\n",
task->tk_pid);
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
return NULL;
case RPC_AUTH_TOOWEAK:
printk(KERN_NOTICE "call_verify: server requires stronger "
if (task->tk_garb_retry) {
task->tk_garb_retry--;
dprintk(KERN_WARNING "RPC: garbage, retrying %4d\n", task->tk_pid);
- task->tk_action = call_encode;
+ task->tk_action = call_bind;
return NULL;
}
printk(KERN_WARNING "RPC: garbage, exit EIO\n");
* Local functions
*/
static void xprt_request_init(struct rpc_task *, struct rpc_xprt *);
-static void do_xprt_transmit(struct rpc_task *);
static inline void do_xprt_reserve(struct rpc_task *);
static void xprt_disconnect(struct rpc_xprt *);
static void xprt_conn_status(struct rpc_task *task);
* Place the actual RPC call.
* We have to copy the iovec because sendmsg fiddles with its contents.
*/
-void
-xprt_transmit(struct rpc_task *task)
+int
+xprt_prepare_transmit(struct rpc_task *task)
{
struct rpc_rqst *req = task->tk_rqstp;
struct rpc_xprt *xprt = req->rq_xprt;
+ int err = 0;
- dprintk("RPC: %4d xprt_transmit(%x)\n", task->tk_pid,
- *(u32 *)(req->rq_svec[0].iov_base));
+ dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid);
if (xprt->shutdown)
- task->tk_status = -EIO;
+ return -EIO;
if (!xprt_connected(xprt))
- task->tk_status = -ENOTCONN;
-
- if (task->tk_status < 0)
- return;
+ return -ENOTCONN;
if (task->tk_rpcwait)
rpc_remove_wait_queue(task);
- /* set up everything as needed. */
- /* Write the record marker */
- if (xprt->stream) {
- u32 *marker = req->rq_svec[0].iov_base;
-
- *marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
- }
-
spin_lock_bh(&xprt->sock_lock);
if (!__xprt_lock_write(xprt, task)) {
- spin_unlock_bh(&xprt->sock_lock);
- return;
+ err = -EAGAIN;
+ goto out_unlock;
}
if (list_empty(&req->rq_list)) {
list_add_tail(&req->rq_list, &xprt->recv);
req->rq_received = 0;
}
+out_unlock:
spin_unlock_bh(&xprt->sock_lock);
-
- do_xprt_transmit(task);
+ return err;
}
-static void
-do_xprt_transmit(struct rpc_task *task)
+void
+xprt_transmit(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
struct rpc_rqst *req = task->tk_rqstp;
int status, retry = 0;
+ dprintk("RPC: %4d xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
+
+ /* set up everything as needed. */
+ /* Write the record marker */
+ if (xprt->stream) {
+ u32 *marker = req->rq_svec[0].iov_base;
+
+ *marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
+ }
+
/* Continue transmitting the packet/record. We must be careful
* to cope with writespace callbacks arriving _after_ we have
* called xprt_sendmsg().