SUNRPC: Add RPC task and client level options to disable the resend timeout
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 24 Sep 2013 16:00:27 +0000 (12:00 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 1 Oct 2013 22:22:11 +0000 (18:22 -0400)
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
include/linux/sunrpc/clnt.h
include/linux/sunrpc/sched.h
net/sunrpc/clnt.c
net/sunrpc/xprt.c

index 6740801..943ee89 100644 (file)
@@ -49,6 +49,7 @@ struct rpc_clnt {
 
        unsigned int            cl_softrtry : 1,/* soft timeouts */
                                cl_discrtry : 1,/* disconnect before retry */
+                               cl_noretranstimeo: 1,/* No retransmit timeouts */
                                cl_autobind : 1,/* use getport() */
                                cl_chatty   : 1;/* be verbose */
 
@@ -126,6 +127,7 @@ struct rpc_create_args {
 #define RPC_CLNT_CREATE_QUIET          (1UL << 6)
 #define RPC_CLNT_CREATE_INFINITE_SLOTS (1UL << 7)
 #define RPC_CLNT_CREATE_NO_IDLE_TIMEOUT        (1UL << 8)
+#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT     (1UL << 9)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
 struct rpc_clnt        *rpc_bind_new_program(struct rpc_clnt *,
index 096ee58..3a847de 100644 (file)
@@ -122,6 +122,7 @@ struct rpc_task_setup {
 #define RPC_TASK_SENT          0x0800          /* message was sent */
 #define RPC_TASK_TIMEOUT       0x1000          /* fail with ETIMEDOUT on timeout */
 #define RPC_TASK_NOCONNECT     0x2000          /* return ENOTCONN if not connected */
+#define RPC_TASK_NO_RETRANS_TIMEOUT    0x4000          /* wait forever for a reply */
 
 #define RPC_IS_ASYNC(t)                ((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SWAPPER(t)      ((t)->tk_flags & RPC_TASK_SWAPPER)
index fa50e42..b585250 100644 (file)
@@ -772,6 +772,8 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
                atomic_inc(&clnt->cl_count);
                if (clnt->cl_softrtry)
                        task->tk_flags |= RPC_TASK_SOFT;
+               if (clnt->cl_noretranstimeo)
+                       task->tk_flags |= RPC_TASK_NO_RETRANS_TIMEOUT;
                if (sk_memalloc_socks()) {
                        struct rpc_xprt *xprt;
 
@@ -1898,7 +1900,8 @@ call_status(struct rpc_task *task)
                rpc_delay(task, 3*HZ);
        case -ETIMEDOUT:
                task->tk_action = call_timeout;
-               if (task->tk_client->cl_discrtry)
+               if (!(task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT)
+                   && task->tk_client->cl_discrtry)
                        xprt_conditional_disconnect(req->rq_xprt,
                                        req->rq_connect_cookie);
                break;
index 2326af5..d166d99 100644 (file)
@@ -873,9 +873,18 @@ bool xprt_prepare_transmit(struct rpc_task *task)
        dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid);
 
        spin_lock_bh(&xprt->transport_lock);
-       if (req->rq_reply_bytes_recvd && !req->rq_bytes_sent) {
-               task->tk_status = req->rq_reply_bytes_recvd;
-               goto out_unlock;
+       if (!req->rq_bytes_sent) {
+               if (req->rq_reply_bytes_recvd) {
+                       task->tk_status = req->rq_reply_bytes_recvd;
+                       goto out_unlock;
+               }
+               if ((task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT)
+                   && xprt_connected(xprt)
+                   && req->rq_connect_cookie == xprt->connect_cookie) {
+                       xprt->ops->set_retrans_timeout(task);
+                       rpc_sleep_on(&xprt->pending, task, xprt_timer);
+                       goto out_unlock;
+               }
        }
        if (!xprt->ops->reserve_xprt(xprt, task)) {
                task->tk_status = -EAGAIN;