diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-02-06 18:26:11 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-13 01:40:45 -0500 |
commit | 43d78ef2ba5bec26d0315859e8324bfc0be23766 (patch) | |
tree | 6ea576e0a20a11745c7a45b2a15dd855a45b655a /fs | |
parent | a301b777714087ea1d63dbec0173a13d416cd7a9 (diff) |
NFS: disconnect before retrying NFSv4 requests over TCP
RFC3530 section 3.1.1 states an NFSv4 client MUST NOT send a request
twice on the same connection unless it is the NULL procedure. Section
3.1.1 suggests that the client should disconnect and reconnect if it
wants to retry a request.
Implement this by adding an rpc_clnt flag that an ULP can use to
specify that the underlying transport should be disconnected on a
major timeout. The NFSv4 client asserts this new flag, and requests
no retries after a minor retransmit timeout.
Note that disconnecting on a retransmit is in general not safe to do
if the RPC client does not reuse the TCP port number when reconnecting.
See http://bugzilla.linux-nfs.org/show_bug.cgi?id=6
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/client.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a3191f023490..c46e94fed9eb 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -394,7 +394,8 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |||
394 | static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | 394 | static int nfs_create_rpc_client(struct nfs_client *clp, int proto, |
395 | unsigned int timeo, | 395 | unsigned int timeo, |
396 | unsigned int retrans, | 396 | unsigned int retrans, |
397 | rpc_authflavor_t flavor) | 397 | rpc_authflavor_t flavor, |
398 | int flags) | ||
398 | { | 399 | { |
399 | struct rpc_timeout timeparms; | 400 | struct rpc_timeout timeparms; |
400 | struct rpc_clnt *clnt = NULL; | 401 | struct rpc_clnt *clnt = NULL; |
@@ -407,6 +408,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | |||
407 | .program = &nfs_program, | 408 | .program = &nfs_program, |
408 | .version = clp->rpc_ops->version, | 409 | .version = clp->rpc_ops->version, |
409 | .authflavor = flavor, | 410 | .authflavor = flavor, |
411 | .flags = flags, | ||
410 | }; | 412 | }; |
411 | 413 | ||
412 | if (!IS_ERR(clp->cl_rpcclient)) | 414 | if (!IS_ERR(clp->cl_rpcclient)) |
@@ -548,7 +550,7 @@ static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data * | |||
548 | * - RFC 2623, sec 2.3.2 | 550 | * - RFC 2623, sec 2.3.2 |
549 | */ | 551 | */ |
550 | error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, | 552 | error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, |
551 | RPC_AUTH_UNIX); | 553 | RPC_AUTH_UNIX, 0); |
552 | if (error < 0) | 554 | if (error < 0) |
553 | goto error; | 555 | goto error; |
554 | nfs_mark_client_ready(clp, NFS_CS_READY); | 556 | nfs_mark_client_ready(clp, NFS_CS_READY); |
@@ -868,7 +870,8 @@ static int nfs4_init_client(struct nfs_client *clp, | |||
868 | /* Check NFS protocol revision and initialize RPC op vector */ | 870 | /* Check NFS protocol revision and initialize RPC op vector */ |
869 | clp->rpc_ops = &nfs_v4_clientops; | 871 | clp->rpc_ops = &nfs_v4_clientops; |
870 | 872 | ||
871 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); | 873 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour, |
874 | RPC_CLNT_CREATE_DISCRTRY); | ||
872 | if (error < 0) | 875 | if (error < 0) |
873 | goto error; | 876 | goto error; |
874 | memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); | 877 | memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); |