Pull mca-check-psp into release branch
[powerpc.git] / net / sunrpc / clnt.c
index 5a8f01d..61c3abe 100644 (file)
@@ -55,6 +55,7 @@ static void   call_bind(struct rpc_task *task);
 static void    call_bind_status(struct rpc_task *task);
 static void    call_transmit(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_refreshresult(struct rpc_task *task);
 static void    call_timeout(struct rpc_task *task);
@@ -672,19 +673,29 @@ call_allocate(struct rpc_task *task)
        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
  */
 static void
 call_encode(struct rpc_task *task)
 {
-       struct rpc_clnt *clnt = task->tk_client;
        struct rpc_rqst *req = task->tk_rqstp;
        struct xdr_buf *sndbuf = &req->rq_snd_buf;
        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
        unsigned int    bufsiz;
        kxdrproc_t      encode;
-       int             status;
        u32             *p;
 
        dprintk("RPC: %4d call_encode (status %d)\n", 
@@ -712,11 +723,15 @@ call_encode(struct rpc_task *task)
                rpc_exit(task, -EIO);
                return;
        }
-       if (encode && (status = rpcauth_wrap_req(task, encode, req, p,
-                                                task->tk_msg.rpc_argp)) < 0) {
-               printk(KERN_WARNING "%s: can't encode arguments: %d\n",
-                               clnt->cl_protname, -status);
-               rpc_exit(task, status);
+       if (encode == NULL)
+               return;
+
+       task->tk_status = rpcauth_wrap_req(task, encode, req, p,
+                       task->tk_msg.rpc_argp);
+       if (task->tk_status == -ENOMEM) {
+               /* XXX: Is this sane? */
+               rpc_delay(task, 3*HZ);
+               task->tk_status = -EAGAIN;
        }
 }
 
@@ -759,7 +774,8 @@ call_bind_status(struct rpc_task *task)
        case -EACCES:
                dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n",
                                task->tk_pid);
-               break;
+               rpc_delay(task, 3*HZ);
+               goto retry_bind;
        case -ETIMEDOUT:
                dprintk("RPC: %4d rpcbind request timed out\n",
                                task->tk_pid);
@@ -864,10 +880,14 @@ call_transmit(struct rpc_task *task)
        if (task->tk_status != 0)
                return;
        /* Encode here so that rpcsec_gss can use correct sequence number. */
-       if (!task->tk_rqstp->rq_bytes_sent)
+       if (rpc_task_need_encode(task)) {
+               task->tk_rqstp->rq_bytes_sent = 0;
                call_encode(task);
-       if (task->tk_status < 0)
-               return;
+               /* Did the encode result in an error condition? */
+               if (task->tk_status != 0)
+                       goto out_nosend;
+       }
+       task->tk_action = call_transmit_status;
        xprt_transmit(task);
        if (task->tk_status < 0)
                return;
@@ -875,6 +895,11 @@ call_transmit(struct rpc_task *task)
                task->tk_action = NULL;
                rpc_wake_up_task(task);
        }
+       return;
+out_nosend:
+       /* release socket write lock before attempting to handle error */
+       xprt_abort_transmit(task);
+       rpc_task_force_reencode(task);
 }
 
 /*
@@ -906,7 +931,6 @@ call_status(struct rpc_task *task)
                break;
        case -ECONNREFUSED:
        case -ENOTCONN:
-               req->rq_bytes_sent = 0;
                if (clnt->cl_autobind)
                        clnt->cl_port = 0;
                task->tk_action = call_bind;
@@ -928,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
  *     same XID for all retransmits.
  */