Commit eab5c084 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

[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: default avatarChuck Lever <cel@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent da351878
...@@ -358,6 +358,35 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor) ...@@ -358,6 +358,35 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
return no_root_error; return no_root_error;
} }
static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
{
to->to_initval = timeo * HZ / 10;
to->to_retries = retrans;
if (!to->to_retries)
to->to_retries = 2;
switch (proto) {
case IPPROTO_TCP:
if (!to->to_initval)
to->to_initval = 60 * HZ;
if (to->to_initval > RPC_MAX_TCP_TIMEOUT)
to->to_initval = RPC_MAX_TCP_TIMEOUT;
to->to_increment = to->to_initval;
to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
to->to_exponential = 0;
break;
case IPPROTO_UDP:
default:
if (!to->to_initval)
to->to_initval = 11 * HZ / 10;
if (to->to_initval > RPC_MAX_UDP_TIMEOUT)
to->to_initval = RPC_MAX_UDP_TIMEOUT;
to->to_maxval = RPC_MAX_UDP_TIMEOUT;
to->to_exponential = 1;
break;
}
}
/* /*
* Create an RPC client handle. * Create an RPC client handle.
*/ */
...@@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) ...@@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
struct rpc_timeout timeparms; struct rpc_timeout timeparms;
struct rpc_xprt *xprt = NULL; struct rpc_xprt *xprt = NULL;
struct rpc_clnt *clnt = NULL; struct rpc_clnt *clnt = NULL;
int tcp = (data->flags & NFS_MOUNT_TCP); int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
/* Initialize timeout values */ nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
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)
timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;
if (!timeparms.to_retries)
timeparms.to_retries = 5;
/* create transport and client */ /* create transport and client */
xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, xprt = xprt_create_proto(proto, &server->addr, &timeparms);
&server->addr, &timeparms);
if (IS_ERR(xprt)) { if (IS_ERR(xprt)) {
dprintk("%s: cannot create RPC transport. Error = %ld\n", dprintk("%s: cannot create RPC transport. Error = %ld\n",
__FUNCTION__, PTR_ERR(xprt)); __FUNCTION__, PTR_ERR(xprt));
...@@ -1674,7 +1693,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1674,7 +1693,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
struct rpc_clnt *clnt = NULL; struct rpc_clnt *clnt = NULL;
struct rpc_timeout timeparms; struct rpc_timeout timeparms;
rpc_authflavor_t authflavour; rpc_authflavor_t authflavour;
int proto, err = -EIO; int err = -EIO;
sb->s_blocksize_bits = 0; sb->s_blocksize_bits = 0;
sb->s_blocksize = 0; sb->s_blocksize = 0;
...@@ -1692,30 +1711,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1692,30 +1711,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
server->acdirmax = data->acdirmax*HZ; server->acdirmax = data->acdirmax*HZ;
server->rpc_ops = &nfs_v4_clientops; server->rpc_ops = &nfs_v4_clientops;
/* Initialize timeout values */
timeparms.to_initval = data->timeo * HZ / 10; nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
timeparms.to_retries = data->retrans;
timeparms.to_exponential = 1;
if (!timeparms.to_retries)
timeparms.to_retries = 5;
proto = data->proto;
/* 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;
default:
return -EINVAL;
}
clp = nfs4_get_client(&server->addr.sin_addr); clp = nfs4_get_client(&server->addr.sin_addr);
if (!clp) { if (!clp) {
...@@ -1740,7 +1737,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1740,7 +1737,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
down_write(&clp->cl_sem); down_write(&clp->cl_sem);
if (IS_ERR(clp->cl_rpcclient)) { if (IS_ERR(clp->cl_rpcclient)) {
xprt = xprt_create_proto(proto, &server->addr, &timeparms); xprt = xprt_create_proto(data->proto, &server->addr, &timeparms);
if (IS_ERR(xprt)) { if (IS_ERR(xprt)) {
up_write(&clp->cl_sem); up_write(&clp->cl_sem);
err = PTR_ERR(xprt); err = PTR_ERR(xprt);
......
...@@ -1453,7 +1453,7 @@ xprt_default_timeout(struct rpc_timeout *to, int proto) ...@@ -1453,7 +1453,7 @@ xprt_default_timeout(struct rpc_timeout *to, int proto)
if (proto == IPPROTO_UDP) if (proto == IPPROTO_UDP)
xprt_set_timeout(to, 5, 5 * HZ); xprt_set_timeout(to, 5, 5 * HZ);
else else
xprt_set_timeout(to, 5, 60 * HZ); xprt_set_timeout(to, 2, 60 * HZ);
} }
/* /*
...@@ -1464,7 +1464,7 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr) ...@@ -1464,7 +1464,7 @@ xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr)
{ {
to->to_initval = to->to_initval =
to->to_increment = incr; to->to_increment = incr;
to->to_maxval = incr * retr; to->to_maxval = to->to_initval + (incr * retr);
to->to_retries = retr; to->to_retries = retr;
to->to_exponential = 0; to->to_exponential = 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment