aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2012-07-11 16:30:50 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-07-16 15:12:16 -0400
commitde734831224e74fcaf8917386e33644c4243db95 (patch)
treecc162230a4ae0086b5d2c4bb9e9163d18d82b826 /fs
parent46a87b8a7b939900d779042da7097bf330ab787f (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.c47
-rw-r--r--fs/nfs/nfs4state.c7
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
4070int nfs4_proc_setclientid_confirm(struct nfs_client *clp, 4056int 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;