NFS: Don't use GFP_KERNEL in rpcsec_gss downcalls
[safe/jmp/linux-2.6] / net / sunrpc / clnt.c
index c1e467e..8c7b543 100644 (file)
@@ -79,7 +79,7 @@ static void   call_connect_status(struct rpc_task *task);
 
 static __be32  *rpc_encode_header(struct rpc_task *task);
 static __be32  *rpc_verify_header(struct rpc_task *task);
-static int     rpc_ping(struct rpc_clnt *clnt, int flags);
+static int     rpc_ping(struct rpc_clnt *clnt);
 
 static void rpc_register_client(struct rpc_clnt *clnt)
 {
@@ -288,6 +288,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
                .srcaddr = args->saddress,
                .dstaddr = args->address,
                .addrlen = args->addrsize,
+               .bc_xprt = args->bc_xprt,
        };
        char servername[48];
 
@@ -339,7 +340,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
                return clnt;
 
        if (!(args->flags & RPC_CLNT_CREATE_NOPING)) {
-               int err = rpc_ping(clnt, RPC_TASK_SOFT);
+               int err = rpc_ping(clnt);
                if (err != 0) {
                        rpc_shutdown_client(clnt);
                        return ERR_PTR(err);
@@ -527,7 +528,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
        clnt->cl_prog     = program->number;
        clnt->cl_vers     = version->number;
        clnt->cl_stats    = program->stats;
-       err = rpc_ping(clnt, RPC_TASK_SOFT);
+       err = rpc_ping(clnt);
        if (err != 0) {
                rpc_shutdown_client(clnt);
                clnt = ERR_PTR(err);
@@ -555,26 +556,16 @@ static const struct rpc_call_ops rpc_default_ops = {
  */
 struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
 {
-       struct rpc_task *task, *ret;
+       struct rpc_task *task;
 
        task = rpc_new_task(task_setup_data);
-       if (task == NULL) {
-               rpc_release_calldata(task_setup_data->callback_ops,
-                               task_setup_data->callback_data);
-               ret = ERR_PTR(-ENOMEM);
+       if (IS_ERR(task))
                goto out;
-       }
 
-       if (task->tk_status != 0) {
-               ret = ERR_PTR(task->tk_status);
-               rpc_put_task(task);
-               goto out;
-       }
        atomic_inc(&task->tk_count);
        rpc_execute(task);
-       ret = task;
 out:
-       return ret;
+       return task;
 }
 EXPORT_SYMBOL_GPL(rpc_run_task);
 
@@ -639,10 +630,11 @@ EXPORT_SYMBOL_GPL(rpc_call_async);
 /**
  * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
  * rpc_execute against it
- * @ops: RPC call ops
+ * @req: RPC request
+ * @tk_ops: RPC call ops
  */
 struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
-                                       const struct rpc_call_ops *tk_ops)
+                               const struct rpc_call_ops *tk_ops)
 {
        struct rpc_task *task;
        struct xdr_buf *xbufp = &req->rq_snd_buf;
@@ -655,7 +647,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);
-       if (!task) {
+       if (IS_ERR(task)) {
                xprt_free_bc_request(req);
                goto out;
        }
@@ -955,6 +947,7 @@ 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;
 }
 
 static inline void
@@ -1057,7 +1050,7 @@ call_bind_status(struct rpc_task *task)
                goto retry_timeout;
        case -EPFNOSUPPORT:
                /* server doesn't support any rpcbind version we know of */
-               dprintk("RPC: %5u remote rpcbind service unavailable\n",
+               dprintk("RPC: %5u unrecognized remote rpcbind service\n",
                                task->tk_pid);
                break;
        case -EPROTONOSUPPORT:
@@ -1066,6 +1059,21 @@ call_bind_status(struct rpc_task *task)
                task->tk_status = 0;
                task->tk_action = call_bind;
                return;
+       case -ECONNREFUSED:             /* connection problems */
+       case -ECONNRESET:
+       case -ENOTCONN:
+       case -EHOSTDOWN:
+       case -EHOSTUNREACH:
+       case -ENETUNREACH:
+       case -EPIPE:
+               dprintk("RPC: %5u remote rpcbind unreachable: %d\n",
+                               task->tk_pid, task->tk_status);
+               if (!RPC_IS_SOFTCONN(task)) {
+                       rpc_delay(task, 5*HZ);
+                       goto retry_timeout;
+               }
+               status = task->tk_status;
+               break;
        default:
                dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
                                task->tk_pid, -task->tk_status);
@@ -1177,11 +1185,25 @@ static void
 call_transmit_status(struct rpc_task *task)
 {
        task->tk_action = call_status;
+
+       /*
+        * Common case: success.  Force the compiler to put this
+        * test first.
+        */
+       if (task->tk_status == 0) {
+               xprt_end_transmit(task);
+               rpc_task_force_reencode(task);
+               return;
+       }
+
        switch (task->tk_status) {
        case -EAGAIN:
                break;
        default:
+               dprint_status(task);
                xprt_end_transmit(task);
+               rpc_task_force_reencode(task);
+               break;
                /*
                 * Special cases: if we've been waiting on the
                 * socket's write_space() callback, or if the
@@ -1189,11 +1211,16 @@ call_transmit_status(struct rpc_task *task)
                 * then hold onto the transport lock.
                 */
        case -ECONNREFUSED:
-       case -ECONNRESET:
-       case -ENOTCONN:
        case -EHOSTDOWN:
        case -EHOSTUNREACH:
        case -ENETUNREACH:
+               if (RPC_IS_SOFTCONN(task)) {
+                       xprt_end_transmit(task);
+                       rpc_exit(task, task->tk_status);
+                       break;
+               }
+       case -ECONNRESET:
+       case -ENOTCONN:
        case -EPIPE:
                rpc_task_force_reencode(task);
        }
@@ -1343,6 +1370,10 @@ call_timeout(struct rpc_task *task)
        dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
        task->tk_timeouts++;
 
+       if (RPC_IS_SOFTCONN(task)) {
+               rpc_exit(task, -ETIMEDOUT);
+               return;
+       }
        if (RPC_IS_SOFT(task)) {
                if (clnt->cl_chatty)
                        printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
@@ -1672,14 +1703,14 @@ static struct rpc_procinfo rpcproc_null = {
        .p_decode = rpcproc_decode_null,
 };
 
-static int rpc_ping(struct rpc_clnt *clnt, int flags)
+static int rpc_ping(struct rpc_clnt *clnt)
 {
        struct rpc_message msg = {
                .rpc_proc = &rpcproc_null,
        };
        int err;
        msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0);
-       err = rpc_call_sync(clnt, &msg, flags);
+       err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN);
        put_rpccred(msg.rpc_cred);
        return err;
 }