aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-04-24 14:28:18 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-04-24 14:28:18 -0400
commitfd954ae124e8a866e9cc1bc3de9a07be5492f608 (patch)
treeb45b1a58287e2e77afb1da4ed8ead0c3a8688c2d /fs/nfs/nfs4state.c
parentfb8a5ba8114491467c4067ec0330e1c3dcc81d10 (diff)
NFSv4.1: Don't loop forever in nfs4_proc_create_session
If a server for some reason keeps sending NFS4ERR_DELAY errors, we can end up looping forever inside nfs4_proc_create_session, and so the usual mechanisms for detecting if the nfs_client is dead don't work. Fix this by ensuring that we loop inside the nfs4_state_manager thread instead. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 4dfb34b43ffb..4a810c8b0753 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -64,10 +64,15 @@ static LIST_HEAD(nfs4_clientid_list);
64 64
65int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) 65int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
66{ 66{
67 struct nfs4_setclientid_res clid; 67 struct nfs4_setclientid_res clid = {
68 .clientid = clp->cl_clientid,
69 .confirm = clp->cl_confirm,
70 };
68 unsigned short port; 71 unsigned short port;
69 int status; 72 int status;
70 73
74 if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
75 goto do_confirm;
71 port = nfs_callback_tcpport; 76 port = nfs_callback_tcpport;
72 if (clp->cl_addr.ss_family == AF_INET6) 77 if (clp->cl_addr.ss_family == AF_INET6)
73 port = nfs_callback_tcpport6; 78 port = nfs_callback_tcpport6;
@@ -75,10 +80,14 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
75 status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); 80 status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
76 if (status != 0) 81 if (status != 0)
77 goto out; 82 goto out;
83 clp->cl_clientid = clid.clientid;
84 clp->cl_confirm = clid.confirm;
85 set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
86do_confirm:
78 status = nfs4_proc_setclientid_confirm(clp, &clid, cred); 87 status = nfs4_proc_setclientid_confirm(clp, &clid, cred);
79 if (status != 0) 88 if (status != 0)
80 goto out; 89 goto out;
81 clp->cl_clientid = clid.clientid; 90 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
82 nfs4_schedule_state_renewal(clp); 91 nfs4_schedule_state_renewal(clp);
83out: 92out:
84 return status; 93 return status;
@@ -230,13 +239,18 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
230{ 239{
231 int status; 240 int status;
232 241
242 if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
243 goto do_confirm;
233 nfs4_begin_drain_session(clp); 244 nfs4_begin_drain_session(clp);
234 status = nfs4_proc_exchange_id(clp, cred); 245 status = nfs4_proc_exchange_id(clp, cred);
235 if (status != 0) 246 if (status != 0)
236 goto out; 247 goto out;
248 set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
249do_confirm:
237 status = nfs4_proc_create_session(clp); 250 status = nfs4_proc_create_session(clp);
238 if (status != 0) 251 if (status != 0)
239 goto out; 252 goto out;
253 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
240 nfs41_setup_state_renewal(clp); 254 nfs41_setup_state_renewal(clp);
241 nfs_mark_client_ready(clp, NFS_CS_READY); 255 nfs_mark_client_ready(clp, NFS_CS_READY);
242out: 256out:
@@ -1584,20 +1598,22 @@ static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
1584 */ 1598 */
1585static void nfs4_set_lease_expired(struct nfs_client *clp, int status) 1599static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
1586{ 1600{
1587 if (nfs4_has_session(clp)) { 1601 switch (status) {
1588 switch (status) { 1602 case -NFS4ERR_CLID_INUSE:
1589 case -NFS4ERR_DELAY: 1603 case -NFS4ERR_STALE_CLIENTID:
1590 case -NFS4ERR_CLID_INUSE: 1604 clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
1591 case -EAGAIN: 1605 break;
1592 break; 1606 case -NFS4ERR_DELAY:
1607 case -EAGAIN:
1608 ssleep(1);
1609 break;
1593 1610
1594 case -EKEYEXPIRED: 1611 case -EKEYEXPIRED:
1595 nfs4_warn_keyexpired(clp->cl_hostname); 1612 nfs4_warn_keyexpired(clp->cl_hostname);
1596 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery 1613 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
1597 * in nfs4_exchange_id */ 1614 * in nfs4_exchange_id */
1598 default: 1615 default:
1599 return; 1616 return;
1600 }
1601 } 1617 }
1602 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1618 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1603} 1619}