diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2012-07-11 16:30:50 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-07-16 15:12:16 -0400 |
commit | de734831224e74fcaf8917386e33644c4243db95 (patch) | |
tree | cc162230a4ae0086b5d2c4bb9e9163d18d82b826 /fs | |
parent | 46a87b8a7b939900d779042da7097bf330ab787f (diff) |
NFS: Treat NFS4ERR_CLID_INUSE as a fatal error
For NFSv4 minor version 0, currently the cl_id_uniquifier allows the
Linux client to generate a unique nfs_client_id4 string whenever a
server replies with NFS4ERR_CLID_INUSE.
This implementation seems to be based on a flawed reading of RFC
3530. NFS4ERR_CLID_INUSE actually means that the client has presented
this nfs_client_id4 string with a different principal at some time in
the past, and that lease is still in use on the server.
For a Linux client this might be rather difficult to achieve: the
authentication flavor is named right in the nfs_client_id4.id
string. If we change flavors, we change strings automatically.
So, practically speaking, NFS4ERR_CLID_INUSE means there is some other
client using our string. There is not much that can be done to
recover automatically. Let's make it a permanent error.
Remove the recovery logic in nfs4_proc_setclientid(), and remove the
cl_id_uniquifier field from the nfs_client data structure. And,
remove the authentication flavor from the nfs_client_id4 string.
Keeping the authentication flavor in the nfs_client_id4.id string
means that we could have a separate lease for each authentication
flavor used by mounts on the client. But we want just one lease for
all the mounts on this client.
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/nfs4proc.c | 47 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 7 |
2 files changed, 22 insertions, 32 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 74dcd85f0a1d..1148081e1a53 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -4029,42 +4029,28 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
4029 | .rpc_resp = res, | 4029 | .rpc_resp = res, |
4030 | .rpc_cred = cred, | 4030 | .rpc_cred = cred, |
4031 | }; | 4031 | }; |
4032 | int loop = 0; | ||
4033 | int status; | ||
4034 | 4032 | ||
4033 | /* nfs_client_id4 */ | ||
4035 | nfs4_init_boot_verifier(clp, &sc_verifier); | 4034 | nfs4_init_boot_verifier(clp, &sc_verifier); |
4036 | 4035 | rcu_read_lock(); | |
4037 | for(;;) { | 4036 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, |
4038 | rcu_read_lock(); | 4037 | sizeof(setclientid.sc_name), "%s/%s %s", |
4039 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, | 4038 | clp->cl_ipaddr, |
4040 | sizeof(setclientid.sc_name), "%s/%s %s %s %u", | 4039 | rpc_peeraddr2str(clp->cl_rpcclient, |
4041 | clp->cl_ipaddr, | 4040 | RPC_DISPLAY_ADDR), |
4042 | rpc_peeraddr2str(clp->cl_rpcclient, | 4041 | rpc_peeraddr2str(clp->cl_rpcclient, |
4043 | RPC_DISPLAY_ADDR), | 4042 | RPC_DISPLAY_PROTO)); |
4044 | rpc_peeraddr2str(clp->cl_rpcclient, | 4043 | /* cb_client4 */ |
4045 | RPC_DISPLAY_PROTO), | 4044 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
4046 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | ||
4047 | clp->cl_id_uniquifier); | ||
4048 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | ||
4049 | sizeof(setclientid.sc_netid), | 4045 | sizeof(setclientid.sc_netid), |
4050 | rpc_peeraddr2str(clp->cl_rpcclient, | 4046 | rpc_peeraddr2str(clp->cl_rpcclient, |
4051 | RPC_DISPLAY_NETID)); | 4047 | RPC_DISPLAY_NETID)); |
4052 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, | 4048 | rcu_read_unlock(); |
4049 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, | ||
4053 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", | 4050 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
4054 | clp->cl_ipaddr, port >> 8, port & 255); | 4051 | clp->cl_ipaddr, port >> 8, port & 255); |
4055 | rcu_read_unlock(); | ||
4056 | 4052 | ||
4057 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4053 | return rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4058 | if (status != -NFS4ERR_CLID_INUSE) | ||
4059 | break; | ||
4060 | if (loop != 0) { | ||
4061 | ++clp->cl_id_uniquifier; | ||
4062 | break; | ||
4063 | } | ||
4064 | ++loop; | ||
4065 | ssleep(clp->cl_lease_time / HZ + 1); | ||
4066 | } | ||
4067 | return status; | ||
4068 | } | 4054 | } |
4069 | 4055 | ||
4070 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | 4056 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, |
@@ -5262,10 +5248,9 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5262 | nfs4_init_boot_verifier(clp, &verifier); | 5248 | nfs4_init_boot_verifier(clp, &verifier); |
5263 | 5249 | ||
5264 | args.id_len = scnprintf(args.id, sizeof(args.id), | 5250 | args.id_len = scnprintf(args.id, sizeof(args.id), |
5265 | "%s/%s/%u", | 5251 | "%s/%s", |
5266 | clp->cl_ipaddr, | 5252 | clp->cl_ipaddr, |
5267 | clp->cl_rpcclient->cl_nodename, | 5253 | clp->cl_rpcclient->cl_nodename); |
5268 | clp->cl_rpcclient->cl_auth->au_flavor); | ||
5269 | 5254 | ||
5270 | res.server_owner = kzalloc(sizeof(struct nfs41_server_owner), | 5255 | res.server_owner = kzalloc(sizeof(struct nfs41_server_owner), |
5271 | GFP_NOFS); | 5256 | GFP_NOFS); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 1cfc4603fd9a..81eabcdad0e5 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1606,10 +1606,15 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) | |||
1606 | return -ESERVERFAULT; | 1606 | return -ESERVERFAULT; |
1607 | /* Lease confirmation error: retry after purging the lease */ | 1607 | /* Lease confirmation error: retry after purging the lease */ |
1608 | ssleep(1); | 1608 | ssleep(1); |
1609 | case -NFS4ERR_CLID_INUSE: | ||
1610 | case -NFS4ERR_STALE_CLIENTID: | 1609 | case -NFS4ERR_STALE_CLIENTID: |
1611 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | 1610 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
1612 | break; | 1611 | break; |
1612 | case -NFS4ERR_CLID_INUSE: | ||
1613 | pr_err("NFS: Server %s reports our clientid is in use\n", | ||
1614 | clp->cl_hostname); | ||
1615 | nfs_mark_client_ready(clp, -EPERM); | ||
1616 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
1617 | return -EPERM; | ||
1613 | case -EACCES: | 1618 | case -EACCES: |
1614 | if (clp->cl_machine_cred == NULL) | 1619 | if (clp->cl_machine_cred == NULL) |
1615 | return -EACCES; | 1620 | return -EACCES; |