]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - net/sunrpc/clnt.c
SUNRPC: Allow rpc_create() to request that TCP slots be unlimited
[linux-imx.git] / net / sunrpc / clnt.c
index 507b5e84fbdb26f88fab789e37f65a976ef6f198..651245aa829a325743aa1190788bdc9b8ae4dc4d 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/rcupdate.h>
 
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/addr.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/metrics.h>
 #include <linux/sunrpc/bc_xprt.h>
@@ -413,6 +414,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
        };
        char servername[48];
 
+       if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
+               xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
        /*
         * If the caller chooses not to specify a hostname, whip
         * up a string representation of the passed-in address.
@@ -1195,6 +1198,21 @@ size_t rpc_max_payload(struct rpc_clnt *clnt)
 }
 EXPORT_SYMBOL_GPL(rpc_max_payload);
 
+/**
+ * rpc_get_timeout - Get timeout for transport in units of HZ
+ * @clnt: RPC client to query
+ */
+unsigned long rpc_get_timeout(struct rpc_clnt *clnt)
+{
+       unsigned long ret;
+
+       rcu_read_lock();
+       ret = rcu_dereference(clnt->cl_xprt)->timeout->to_initval;
+       rcu_read_unlock();
+       return ret;
+}
+EXPORT_SYMBOL_GPL(rpc_get_timeout);
+
 /**
  * rpc_force_rebind - force transport to check that remote port is unchanged
  * @clnt: client to rebind
@@ -1290,6 +1308,8 @@ call_reserve(struct rpc_task *task)
        xprt_reserve(task);
 }
 
+static void call_retry_reserve(struct rpc_task *task);
+
 /*
  * 1b. Grok the result of xprt_reserve()
  */
@@ -1331,7 +1351,7 @@ call_reserveresult(struct rpc_task *task)
        case -ENOMEM:
                rpc_delay(task, HZ >> 2);
        case -EAGAIN:   /* woken up; retry */
-               task->tk_action = call_reserve;
+               task->tk_action = call_retry_reserve;
                return;
        case -EIO:      /* probably a shutdown */
                break;
@@ -1343,6 +1363,19 @@ call_reserveresult(struct rpc_task *task)
        rpc_exit(task, status);
 }
 
+/*
+ * 1c. Retry reserving an RPC call slot
+ */
+static void
+call_retry_reserve(struct rpc_task *task)
+{
+       dprint_status(task);
+
+       task->tk_status  = 0;
+       task->tk_action  = call_reserveresult;
+       xprt_retry_reserve(task);
+}
+
 /*
  * 2.  Bind and/or refresh the credentials
  */
@@ -1400,7 +1433,7 @@ call_allocate(struct rpc_task *task)
 {
        unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack;
        struct rpc_rqst *req = task->tk_rqstp;
-       struct rpc_xprt *xprt = task->tk_xprt;
+       struct rpc_xprt *xprt = req->rq_xprt;
        struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
 
        dprint_status(task);
@@ -1508,7 +1541,7 @@ rpc_xdr_encode(struct rpc_task *task)
 static void
 call_bind(struct rpc_task *task)
 {
-       struct rpc_xprt *xprt = task->tk_xprt;
+       struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
 
        dprint_status(task);
 
@@ -1602,7 +1635,7 @@ retry_timeout:
 static void
 call_connect(struct rpc_task *task)
 {
-       struct rpc_xprt *xprt = task->tk_xprt;
+       struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
 
        dprintk("RPC: %5u call_connect xprt %p %s connected\n",
                        task->tk_pid, xprt,
@@ -1628,22 +1661,26 @@ call_connect_status(struct rpc_task *task)
 
        dprint_status(task);
 
-       task->tk_status = 0;
-       if (status >= 0 || status == -EAGAIN) {
-               clnt->cl_stats->netreconn++;
-               task->tk_action = call_transmit;
-               return;
-       }
-
        trace_rpc_connect_status(task, status);
        switch (status) {
                /* if soft mounted, test if we've timed out */
        case -ETIMEDOUT:
                task->tk_action = call_timeout;
-               break;
-       default:
-               rpc_exit(task, -EIO);
+               return;
+       case -ECONNREFUSED:
+       case -ECONNRESET:
+       case -ENETUNREACH:
+               if (RPC_IS_SOFTCONN(task))
+                       break;
+               /* retry with existing socket, after a delay */
+       case 0:
+       case -EAGAIN:
+               task->tk_status = 0;
+               clnt->cl_stats->netreconn++;
+               task->tk_action = call_transmit;
+               return;
        }
+       rpc_exit(task, status);
 }
 
 /*
@@ -1685,7 +1722,7 @@ call_transmit(struct rpc_task *task)
        if (rpc_reply_expected(task))
                return;
        task->tk_action = rpc_exit_task;
-       rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
+       rpc_wake_up_queued_task(&task->tk_rqstp->rq_xprt->pending, task);
 }
 
 /*
@@ -1784,7 +1821,7 @@ call_bc_transmit(struct rpc_task *task)
                 */
                printk(KERN_NOTICE "RPC: Could not send backchannel reply "
                        "error: %d\n", task->tk_status);
-               xprt_conditional_disconnect(task->tk_xprt,
+               xprt_conditional_disconnect(req->rq_xprt,
                        req->rq_connect_cookie);
                break;
        default:
@@ -1836,7 +1873,7 @@ call_status(struct rpc_task *task)
        case -ETIMEDOUT:
                task->tk_action = call_timeout;
                if (task->tk_client->cl_discrtry)
-                       xprt_conditional_disconnect(task->tk_xprt,
+                       xprt_conditional_disconnect(req->rq_xprt,
                                        req->rq_connect_cookie);
                break;
        case -ECONNRESET:
@@ -1991,7 +2028,7 @@ out_retry:
        if (task->tk_rqstp == req) {
                req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0;
                if (task->tk_client->cl_discrtry)
-                       xprt_conditional_disconnect(task->tk_xprt,
+                       xprt_conditional_disconnect(req->rq_xprt,
                                        req->rq_connect_cookie);
        }
 }
@@ -2005,7 +2042,7 @@ rpc_encode_header(struct rpc_task *task)
 
        /* FIXME: check buffer size? */
 
-       p = xprt_skip_transport_header(task->tk_xprt, p);
+       p = xprt_skip_transport_header(req->rq_xprt, p);
        *p++ = req->rq_xid;             /* XID */
        *p++ = htonl(RPC_CALL);         /* CALL */
        *p++ = htonl(RPC_VERSION);      /* RPC version */