diff options
author | Chuck Lever <cel@citi.umich.edu> | 2005-08-11 16:25:14 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-09-23 12:38:06 -0400 |
commit | eab5c084b858fd95a873fc2b97de9a9ad937b4ed (patch) | |
tree | 6ba8287570ecc83fed1512bd4901df979221c2ab | |
parent | da35187801732397a7e05fb9e77f3700cc35f5db (diff) |
[PATCH] NFS: use a constant value for TCP retransmit timeouts
Implement a best practice: don't use exponential backoff when computing
retransmit timeout values on TCP connections, but simply retransmit
at regular intervals.
This also fixes a bug introduced when xprt_reset_majortimeo() was added.
Test-plan:
Enable RPC debugging and watch timeout behavior on a NFS/TCP mount.
Version: Thu, 11 Aug 2005 16:02:19 -0400
Signed-off-by: Chuck Lever <cel@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/inode.c | 73 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 4 |
2 files changed, 37 insertions, 40 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6922469d6fc5..b6a1ca508e60 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -358,6 +358,35 @@ out_no_root: | |||
358 | return no_root_error; | 358 | return no_root_error; |
359 | } | 359 | } |
360 | 360 | ||
361 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans) | ||
362 | { | ||
363 | to->to_initval = timeo * HZ / 10; | ||
364 | to->to_retries = retrans; | ||
365 | if (!to->to_retries) | ||
366 | to->to_retries = 2; | ||
367 | |||
368 | switch (proto) { | ||
369 | case IPPROTO_TCP: | ||
370 | if (!to->to_initval) | ||
371 | to->to_initval = 60 * HZ; | ||
372 | if (to->to_initval > RPC_MAX_TCP_TIMEOUT) | ||
373 | to->to_initval = RPC_MAX_TCP_TIMEOUT; | ||
374 | to->to_increment = to->to_initval; | ||
375 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | ||
376 | to->to_exponential = 0; | ||
377 | break; | ||
378 | case IPPROTO_UDP: | ||
379 | default: | ||
380 | if (!to->to_initval) | ||
381 | to->to_initval = 11 * HZ / 10; | ||
382 | if (to->to_initval > RPC_MAX_UDP_TIMEOUT) | ||
383 | to->to_initval = RPC_MAX_UDP_TIMEOUT; | ||
384 | to->to_maxval = RPC_MAX_UDP_TIMEOUT; | ||
385 | to->to_exponential = 1; | ||
386 | break; | ||
387 | } | ||
388 | } | ||
389 | |||
361 | /* | 390 | /* |
362 | * Create an RPC client handle. | 391 | * Create an RPC client handle. |
363 | */ | 392 | */ |
@@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) | |||
367 | struct rpc_timeout timeparms; | 396 | struct rpc_timeout timeparms; |
368 | struct rpc_xprt *xprt = NULL; | 397 | struct rpc_xprt *xprt = NULL; |
369 | struct rpc_clnt *clnt = NULL; | 398 | struct rpc_clnt *clnt = NULL; |
370 | int tcp = (data->flags & NFS_MOUNT_TCP); | 399 | int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; |
371 | |||
372 | /* Initialize timeout values */ | ||
373 | timeparms.to_initval = data->timeo * HZ / 10; | ||
374 | timeparms.to_retries = data->retrans; | ||
375 | timeparms.to_maxval = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT; | ||
376 | timeparms.to_exponential = 1; | ||
377 | 400 | ||
378 | if (!timeparms.to_initval) | 401 | nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans); |
379 | timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10; | ||
380 | if (!timeparms.to_retries) | ||
381 | timeparms.to_retries = 5; | ||
382 | 402 | ||
383 | /* create transport and client */ | 403 | /* create transport and client */ |
384 | xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, | 404 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); |
385 | &server->addr, &timeparms); | ||
386 | if (IS_ERR(xprt)) { | 405 | if (IS_ERR(xprt)) { |
387 | dprintk("%s: cannot create RPC transport. Error = %ld\n", | 406 | dprintk("%s: cannot create RPC transport. Error = %ld\n", |
388 | __FUNCTION__, PTR_ERR(xprt)); | 407 | __FUNCTION__, PTR_ERR(xprt)); |
@@ -1674,7 +1693,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1674 | struct rpc_clnt *clnt = NULL; | 1693 | struct rpc_clnt *clnt = NULL; |
1675 | struct rpc_timeout timeparms; | 1694 | struct rpc_timeout timeparms; |
1676 | rpc_authflavor_t authflavour; | 1695 | rpc_authflavor_t authflavour; |
1677 | int proto, err = -EIO; | 1696 | int err = -EIO; |
1678 | 1697 | ||
1679 | sb->s_blocksize_bits = 0; | 1698 | sb->s_blocksize_bits = 0; |
1680 | sb->s_blocksize = 0; | 1699 | sb->s_blocksize = 0; |
@@ -1692,30 +1711,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1692 | server->acdirmax = data->acdirmax*HZ; | 1711 | server->acdirmax = data->acdirmax*HZ; |
1693 | 1712 | ||
1694 | server->rpc_ops = &nfs_v4_clientops; | 1713 | server->rpc_ops = &nfs_v4_clientops; |
1695 | /* Initialize timeout values */ | ||
1696 | |||
1697 | timeparms.to_initval = data->timeo * HZ / 10; | ||
1698 | timeparms.to_retries = data->retrans; | ||
1699 | timeparms.to_exponential = 1; | ||
1700 | if (!timeparms.to_retries) | ||
1701 | timeparms.to_retries = 5; | ||
1702 | 1714 | ||
1703 | proto = data->proto; | 1715 | nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans); |
1704 | /* Which IP protocol do we use? */ | ||
1705 | switch (proto) { | ||
1706 | case IPPROTO_TCP: | ||
1707 | timeparms.to_maxval = RPC_MAX_TCP_TIMEOUT; | ||
1708 | if (!timeparms.to_initval) | ||
1709 | timeparms.to_initval = 600 * HZ / 10; | ||
1710 | break; | ||
1711 | case IPPROTO_UDP: | ||
1712 | timeparms.to_maxval = RPC_MAX_UDP_TIMEOUT; | ||
1713 | if (!timeparms.to_initval) | ||
1714 | timeparms.to_initval = 11 * HZ / 10; | ||
1715 | break; | ||
1716 | default: | ||
1717 | return -EINVAL; | ||
1718 | } | ||
1719 | 1716 | ||
1720 | clp = nfs4_get_client(&server->addr.sin_addr); | 1717 | clp = nfs4_get_client(&server->addr.sin_addr); |
1721 | if (!clp) { | 1718 | if (!clp) { |
@@ -1740,7 +1737,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1740 | 1737 | ||
1741 | down_write(&clp->cl_sem); | 1738 | down_write(&clp->cl_sem); |
1742 | if (IS_ERR(clp->cl_rpcclient)) { | 1739 | if (IS_ERR(clp->cl_rpcclient)) { |
1743 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); | 1740 | xprt = xprt_create_proto(data->proto, &server->addr, &timeparms); |
1744 | if (IS_ERR(xprt)) { | 1741 | if (IS_ERR(xprt)) { |
1745 | up_write(&clp->cl_sem); | 1742 | up_write(&clp->cl_sem); |
1746 | err = PTR_ERR(xprt); | 1743 | err = PTR_ERR(xprt); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index b28ea0cc0cb7..0e4ffdaa0129 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1453,7 +1453,7 @@ xprt_default_timeout(struct rpc_timeout *to, int proto) | |||
1453 | if (proto == IPPROTO_UDP) | 1453 | if (proto == IPPROTO_UDP) |
1454 | xprt_set_timeout(to, 5, 5 * HZ); | 1454 | xprt_set_timeout(to, 5, 5 * HZ); |
1455 | else | 1455 | else |
1456 | xprt_set_timeout(to, 5, 60 * HZ); | 1456 | xprt_set_timeout(to, 2, 60 * HZ); |
1457 | } | 1457 | } |
1458 | 1458 | ||
1459 | /* | 1459 | /* |
@@ -1464,7 +1464,7 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr) | |||
1464 | { | 1464 | { |
1465 | to->to_initval = | 1465 | to->to_initval = |
1466 | to->to_increment = incr; | 1466 | to->to_increment = incr; |
1467 | to->to_maxval = incr * retr; | 1467 | to->to_maxval = to->to_initval + (incr * retr); |
1468 | to->to_retries = retr; | 1468 | to->to_retries = retr; |
1469 | to->to_exponential = 0; | 1469 | to->to_exponential = 0; |
1470 | } | 1470 | } |