xprtrdma: Modernize ops->connect
authorChuck Lever <chuck.lever@oracle.com>
Wed, 19 Jun 2019 14:33:42 +0000 (10:33 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Tue, 9 Jul 2019 14:30:25 +0000 (10:30 -0400)
Adapt and apply changes that were made to the TCP socket connect
code. See the following commits for details on the purpose of
these changes:

Commit 7196dbb02ea0 ("SUNRPC: Allow changing of the TCP timeout parameters on the fly")
Commit 3851f1cdb2b8 ("SUNRPC: Limit the reconnect backoff timer to the max RPC message timeout")
Commit 02910177aede ("SUNRPC: Fix reconnection timeouts")

Some common transport code is moved to xprt.c to satisfy the code
duplication police.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
include/linux/sunrpc/xprt.h
include/trace/events/rpcrdma.h
net/sunrpc/sched.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/sunrpc/xprtsock.c

index a6d9fce..cc78fd3 100644 (file)
@@ -334,6 +334,9 @@ struct xprt_class {
  */
 struct rpc_xprt                *xprt_create_transport(struct xprt_create *args);
 void                   xprt_connect(struct rpc_task *task);
+unsigned long          xprt_reconnect_delay(const struct rpc_xprt *xprt);
+void                   xprt_reconnect_backoff(struct rpc_xprt *xprt,
+                                              unsigned long init_to);
 void                   xprt_reserve(struct rpc_task *task);
 void                   xprt_retry_reserve(struct rpc_task *task);
 int                    xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
index 98023d9..f6a4eaa 100644 (file)
@@ -375,6 +375,37 @@ DEFINE_RXPRT_EVENT(xprtrdma_op_inject_dsc);
 DEFINE_RXPRT_EVENT(xprtrdma_op_close);
 DEFINE_RXPRT_EVENT(xprtrdma_op_connect);
 
+TRACE_EVENT(xprtrdma_op_set_cto,
+       TP_PROTO(
+               const struct rpcrdma_xprt *r_xprt,
+               unsigned long connect,
+               unsigned long reconnect
+       ),
+
+       TP_ARGS(r_xprt, connect, reconnect),
+
+       TP_STRUCT__entry(
+               __field(const void *, r_xprt)
+               __field(unsigned long, connect)
+               __field(unsigned long, reconnect)
+               __string(addr, rpcrdma_addrstr(r_xprt))
+               __string(port, rpcrdma_portstr(r_xprt))
+       ),
+
+       TP_fast_assign(
+               __entry->r_xprt = r_xprt;
+               __entry->connect = connect;
+               __entry->reconnect = reconnect;
+               __assign_str(addr, rpcrdma_addrstr(r_xprt));
+               __assign_str(port, rpcrdma_portstr(r_xprt));
+       ),
+
+       TP_printk("peer=[%s]:%s r_xprt=%p: connect=%lu reconnect=%lu",
+               __get_str(addr), __get_str(port), __entry->r_xprt,
+               __entry->connect / HZ, __entry->reconnect / HZ
+       )
+);
+
 TRACE_EVENT(xprtrdma_qp_event,
        TP_PROTO(
                const struct rpcrdma_xprt *r_xprt,
index bb04ae5..5ad5dea 100644 (file)
@@ -58,6 +58,7 @@ static struct rpc_wait_queue delay_queue;
  */
 struct workqueue_struct *rpciod_workqueue __read_mostly;
 struct workqueue_struct *xprtiod_workqueue __read_mostly;
+EXPORT_SYMBOL_GPL(xprtiod_workqueue);
 
 unsigned long
 rpc_task_timeout(const struct rpc_task *task)
index ad21880..b1f54b7 100644 (file)
@@ -850,6 +850,38 @@ void xprt_connect(struct rpc_task *task)
        xprt_release_write(xprt, task);
 }
 
+/**
+ * xprt_reconnect_delay - compute the wait before scheduling a connect
+ * @xprt: transport instance
+ *
+ */
+unsigned long xprt_reconnect_delay(const struct rpc_xprt *xprt)
+{
+       unsigned long start, now = jiffies;
+
+       start = xprt->stat.connect_start + xprt->reestablish_timeout;
+       if (time_after(start, now))
+               return start - now;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xprt_reconnect_delay);
+
+/**
+ * xprt_reconnect_backoff - compute the new re-establish timeout
+ * @xprt: transport instance
+ * @init_to: initial reestablish timeout
+ *
+ */
+void xprt_reconnect_backoff(struct rpc_xprt *xprt, unsigned long init_to)
+{
+       xprt->reestablish_timeout <<= 1;
+       if (xprt->reestablish_timeout > xprt->max_reconnect_timeout)
+               xprt->reestablish_timeout = xprt->max_reconnect_timeout;
+       if (xprt->reestablish_timeout < init_to)
+               xprt->reestablish_timeout = init_to;
+}
+EXPORT_SYMBOL_GPL(xprt_reconnect_backoff);
+
 enum xprt_xid_rb_cmp {
        XID_RB_EQUAL,
        XID_RB_LEFT,
index 3688e07..4993aa4 100644 (file)
@@ -298,6 +298,7 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
        module_put(THIS_MODULE);
 }
 
+/* 60 second timeout, no retries */
 static const struct rpc_timeout xprt_rdma_default_timeout = {
        .to_initval = 60 * HZ,
        .to_maxval = 60 * HZ,
@@ -323,8 +324,9 @@ xprt_setup_rdma(struct xprt_create *args)
        if (!xprt)
                return ERR_PTR(-ENOMEM);
 
-       /* 60 second timeout, no retries */
        xprt->timeout = &xprt_rdma_default_timeout;
+       xprt->connect_timeout = xprt->timeout->to_initval;
+       xprt->max_reconnect_timeout = xprt->timeout->to_maxval;
        xprt->bind_timeout = RPCRDMA_BIND_TO;
        xprt->reestablish_timeout = RPCRDMA_INIT_REEST_TO;
        xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO;
@@ -487,31 +489,64 @@ xprt_rdma_timer(struct rpc_xprt *xprt, struct rpc_task *task)
 }
 
 /**
- * xprt_rdma_connect - try to establish a transport connection
+ * xprt_rdma_set_connect_timeout - set timeouts for establishing a connection
+ * @xprt: controlling transport instance
+ * @connect_timeout: reconnect timeout after client disconnects
+ * @reconnect_timeout: reconnect timeout after server disconnects
+ *
+ */
+static void xprt_rdma_tcp_set_connect_timeout(struct rpc_xprt *xprt,
+                                             unsigned long connect_timeout,
+                                             unsigned long reconnect_timeout)
+{
+       struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
+
+       trace_xprtrdma_op_set_cto(r_xprt, connect_timeout, reconnect_timeout);
+
+       spin_lock(&xprt->transport_lock);
+
+       if (connect_timeout < xprt->connect_timeout) {
+               struct rpc_timeout to;
+               unsigned long initval;
+
+               to = *xprt->timeout;
+               initval = connect_timeout;
+               if (initval < RPCRDMA_INIT_REEST_TO << 1)
+                       initval = RPCRDMA_INIT_REEST_TO << 1;
+               to.to_initval = initval;
+               to.to_maxval = initval;
+               r_xprt->rx_timeout = to;
+               xprt->timeout = &r_xprt->rx_timeout;
+               xprt->connect_timeout = connect_timeout;
+       }
+
+       if (reconnect_timeout < xprt->max_reconnect_timeout)
+               xprt->max_reconnect_timeout = reconnect_timeout;
+
+       spin_unlock(&xprt->transport_lock);
+}
+
+/**
+ * xprt_rdma_connect - schedule an attempt to reconnect
  * @xprt: transport state
- * @task: RPC scheduler context
+ * @task: RPC scheduler context (unused)
  *
  */
 static void
 xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
 {
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
+       unsigned long delay;
 
        trace_xprtrdma_op_connect(r_xprt);
+
+       delay = 0;
        if (r_xprt->rx_ep.rep_connected != 0) {
-               /* Reconnect */
-               schedule_delayed_work(&r_xprt->rx_connect_worker,
-                                     xprt->reestablish_timeout);
-               xprt->reestablish_timeout <<= 1;
-               if (xprt->reestablish_timeout > RPCRDMA_MAX_REEST_TO)
-                       xprt->reestablish_timeout = RPCRDMA_MAX_REEST_TO;
-               else if (xprt->reestablish_timeout < RPCRDMA_INIT_REEST_TO)
-                       xprt->reestablish_timeout = RPCRDMA_INIT_REEST_TO;
-       } else {
-               schedule_delayed_work(&r_xprt->rx_connect_worker, 0);
-               if (!RPC_IS_ASYNC(task))
-                       flush_delayed_work(&r_xprt->rx_connect_worker);
+               delay = xprt_reconnect_delay(xprt);
+               xprt_reconnect_backoff(xprt, RPCRDMA_INIT_REEST_TO);
        }
+       queue_delayed_work(xprtiod_workqueue, &r_xprt->rx_connect_worker,
+                          delay);
 }
 
 /**
@@ -769,6 +804,7 @@ static const struct rpc_xprt_ops xprt_rdma_procs = {
        .send_request           = xprt_rdma_send_request,
        .close                  = xprt_rdma_close,
        .destroy                = xprt_rdma_destroy,
+       .set_connect_timeout    = xprt_rdma_tcp_set_connect_timeout,
        .print_stats            = xprt_rdma_print_stats,
        .enable_swap            = xprt_rdma_enable_swap,
        .disable_swap           = xprt_rdma_disable_swap,
index 117e328..8378f45 100644 (file)
@@ -432,6 +432,7 @@ struct rpcrdma_xprt {
        struct rpcrdma_ep       rx_ep;
        struct rpcrdma_buffer   rx_buf;
        struct delayed_work     rx_connect_worker;
+       struct rpc_timeout      rx_timeout;
        struct rpcrdma_stats    rx_stats;
 };
 
index c69951e..b154600 100644 (file)
@@ -2402,25 +2402,6 @@ out:
        xprt_wake_pending_tasks(xprt, status);
 }
 
-static unsigned long xs_reconnect_delay(const struct rpc_xprt *xprt)
-{
-       unsigned long start, now = jiffies;
-
-       start = xprt->stat.connect_start + xprt->reestablish_timeout;
-       if (time_after(start, now))
-               return start - now;
-       return 0;
-}
-
-static void xs_reconnect_backoff(struct rpc_xprt *xprt)
-{
-       xprt->reestablish_timeout <<= 1;
-       if (xprt->reestablish_timeout > xprt->max_reconnect_timeout)
-               xprt->reestablish_timeout = xprt->max_reconnect_timeout;
-       if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
-               xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
-}
-
 /**
  * xs_connect - connect a socket to a remote endpoint
  * @xprt: pointer to transport structure
@@ -2450,8 +2431,8 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
                /* Start by resetting any existing state */
                xs_reset_transport(transport);
 
-               delay = xs_reconnect_delay(xprt);
-               xs_reconnect_backoff(xprt);
+               delay = xprt_reconnect_delay(xprt);
+               xprt_reconnect_backoff(xprt, XS_TCP_INIT_REEST_TO);
 
        } else
                dprintk("RPC:       xs_connect scheduled xprt %p\n", xprt);