[PATCH] check initial RPC timeout values more carefully

Chuck Lever (cel@citi.umich.edu)
Tue, 26 Nov 2002 15:00:17 -0500 (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/