[PATCH] check initial RPC timeout values more carefully

From: Chuck Lever (cel@citi.umich.edu)
Date: Tue Nov 26 2002 - 15:00:17 EST


Description:
  this patch provides better checking of initial RPC timeout values, and
  moves protocol-specific setup (part of which is timeout value setup)
  into separate functions. this will ease the addition of support for new
  networking protocols later.

Apply Against:
  2.5.49

Test status:
  Compiles, links, and boots.

diff -Naur 05-timeout/fs/nfs/inode.c 06-timeout-check/fs/nfs/inode.c
--- 05-timeout/fs/nfs/inode.c Fri Nov 22 16:40:55 2002
+++ 06-timeout-check/fs/nfs/inode.c Mon Nov 25 13:28:45 2002
@@ -392,7 +392,6 @@
         /* Initialize timeout values */
         timeparms.to_initval = data->timeo * HZ / 10;
         timeparms.to_retries = data->retrans;
- timeparms.to_maxval = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
         timeparms.to_exponential = 1;
 
         if (!timeparms.to_initval)
@@ -1307,12 +1306,10 @@
         /* Which IP protocol do we use? */
         switch (proto) {
         case IPPROTO_TCP:
- timeparms.to_maxval = RPC_MAX_TCP_TIMEOUT;
                 if (!timeparms.to_initval)
                         timeparms.to_initval = 600 * HZ / 10;
                 break;
         case IPPROTO_UDP:
- timeparms.to_maxval = RPC_MAX_UDP_TIMEOUT;
                 if (!timeparms.to_initval)
                         timeparms.to_initval = 11 * HZ / 10;
                 break;
diff -Naur 05-timeout/include/linux/sunrpc/xprt.h 06-timeout-check/include/linux/sunrpc/xprt.h
--- 05-timeout/include/linux/sunrpc/xprt.h Mon Nov 25 13:26:36 2002
+++ 06-timeout-check/include/linux/sunrpc/xprt.h Mon Nov 25 13:28:45 2002
@@ -40,7 +40,21 @@
 #define RPC_INITCWND RPC_CWNDSCALE
 #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
 
+/*
+ * RTO for stream transports should always be long. The RPC client
+ * handles a major timeout by first closing and reconnecting the
+ * underlying stream transport socket.
+ */
+#define RPC_MIN_UDP_TIMEOUT (HZ/10)
+#define RPC_MIN_TCP_TIMEOUT (6*HZ)
+
 /* Default timeout values */
+#define RPC_DEF_UDP_TIMEOUT (5*HZ)
+#define RPC_DEF_UDP_RETRIES (5)
+#define RPC_DEF_TCP_TIMEOUT (60*HZ)
+#define RPC_DEF_TCP_RETRIES (2)
+
+/* Maximum timeout values */
 #define RPC_MAX_UDP_TIMEOUT (60*HZ)
 #define RPC_MAX_TCP_TIMEOUT (600*HZ)
 
@@ -175,7 +189,6 @@
                                         struct rpc_timeout *toparms);
 int xprt_destroy(struct rpc_xprt *);
 void xprt_shutdown(struct rpc_xprt *);
-void xprt_default_timeout(struct rpc_timeout *, int);
 void xprt_set_timeout(struct rpc_timeout *, unsigned int,
                                         unsigned long);
 
diff -Naur 05-timeout/net/sunrpc/xprt.c 06-timeout-check/net/sunrpc/xprt.c
--- 05-timeout/net/sunrpc/xprt.c Mon Nov 25 13:26:36 2002
+++ 06-timeout-check/net/sunrpc/xprt.c Mon Nov 25 13:28:45 2002
@@ -355,10 +355,6 @@
                 to->to_current = to->to_initval;
         }
 
- if (!to->to_current) {
- printk(KERN_WARNING "xprt_adjust_timeout: to_current = 0!\n");
- to->to_current = 5 * HZ;
- }
         pprintk("RPC: %lu %s\n", jiffies,
                         to->to_retries? "retrans" : "timeout");
         return;
@@ -1327,18 +1323,6 @@
 }
 
 /*
- * Set default timeout parameters
- */
-void
-xprt_default_timeout(struct rpc_timeout *to, int proto)
-{
- if (proto == IPPROTO_UDP)
- xprt_set_timeout(to, 5, 5 * HZ);
- else
- xprt_set_timeout(to, 5, 60 * HZ);
-}
-
-/*
  * Set constant timeout
  */
 void
@@ -1352,6 +1336,56 @@
         to->to_exponential = 0;
 }
 
+static void
+xprt_udp_setup(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+ xprt->prot = IPPROTO_UDP;
+
+ xprt->cwnd = RPC_INITCWND;
+
+ /* Set timeout parameters */
+ if (to) {
+ xprt->timeout = *to;
+
+ to->to_maxval = RPC_MAX_UDP_TIMEOUT;
+
+ if (to->to_initval < RPC_MIN_UDP_TIMEOUT)
+ to->to_initval = RPC_MIN_UDP_TIMEOUT;
+ if (to->to_initval > RPC_MAX_UDP_TIMEOUT)
+ to->to_initval = RPC_MAX_UDP_TIMEOUT;
+
+ xprt->timeout.to_current = to->to_initval;
+ } else
+ xprt_set_timeout(&xprt->timeout,
+ RPC_DEF_UDP_RETRIES, RPC_DEF_UDP_TIMEOUT);
+}
+
+static void
+xprt_tcp_setup(struct rpc_xprt *xprt, struct rpc_timeout *to)
+{
+ xprt->prot = IPPROTO_TCP;
+
+ xprt->stream = 1;
+ xprt->nocong = 1;
+ xprt->cwnd = RPC_MAXCWND;
+
+ /* Set timeout parameters */
+ if (to) {
+ xprt->timeout = *to;
+
+ to->to_maxval = RPC_MAX_TCP_TIMEOUT;
+
+ if (to->to_initval < RPC_MIN_TCP_TIMEOUT)
+ to->to_initval = RPC_MIN_TCP_TIMEOUT;
+ if (to->to_initval > RPC_MAX_TCP_TIMEOUT)
+ to->to_initval = RPC_MAX_TCP_TIMEOUT;
+
+ xprt->timeout.to_current = to->to_initval;
+ } else
+ xprt_set_timeout(&xprt->timeout,
+ RPC_DEF_TCP_RETRIES, RPC_DEF_TCP_TIMEOUT);
+}
+
 /*
  * Initialize an RPC client
  */
@@ -1370,26 +1404,26 @@
         memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */
 
         xprt->addr = *ap;
- xprt->prot = proto;
- xprt->stream = (proto == IPPROTO_TCP)? 1 : 0;
- if (xprt->stream) {
- xprt->cwnd = RPC_MAXCWND;
- xprt->nocong = 1;
- } else
- xprt->cwnd = RPC_INITCWND;
+
+ switch (proto) {
+ case IPPROTO_UDP:
+ xprt_udp_setup(xprt, to);
+ break;
+ case IPPROTO_TCP:
+ xprt_tcp_setup(xprt, to);
+ break;
+ default:
+ printk(KERN_WARNING "RPC: unsupported protocol %d\n", proto);
+ kfree(xprt);
+ return NULL;
+ }
+
         spin_lock_init(&xprt->sock_lock);
         spin_lock_init(&xprt->xprt_lock);
         init_waitqueue_head(&xprt->cong_wait);
 
         INIT_LIST_HEAD(&xprt->recv);
 
- /* Set timeout parameters */
- if (to) {
- xprt->timeout = *to;
- xprt->timeout.to_current = to->to_initval;
- } else
- xprt_default_timeout(&xprt->timeout, xprt->prot);
-
         INIT_RPC_WAITQ(&xprt->pending, "xprt_pending");
         INIT_RPC_WAITQ(&xprt->sending, "xprt_sending");
         INIT_RPC_WAITQ(&xprt->resend, "xprt_resend");

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Nov 30 2002 - 22:00:14 EST