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>
This commit is contained in:
Trond Myklebust
2011-04-24 14:28:18 -04:00
parent fb8a5ba811
commit fd954ae124
4 changed files with 40 additions and 53 deletions

View File

@ -3754,18 +3754,17 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
if (status != -NFS4ERR_CLID_INUSE)
break;
if (signalled())
if (loop != 0) {
++clp->cl_id_uniquifier;
break;
if (loop++ & 1)
ssleep(clp->cl_lease_time / HZ + 1);
else
if (++clp->cl_id_uniquifier == 0)
break;
}
++loop;
ssleep(clp->cl_lease_time / HZ + 1);
}
return status;
}
static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
struct nfs4_setclientid_res *arg,
struct rpc_cred *cred)
{
@ -3790,26 +3789,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
return status;
}
int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
struct nfs4_setclientid_res *arg,
struct rpc_cred *cred)
{
long timeout = 0;
int err;
do {
err = _nfs4_proc_setclientid_confirm(clp, arg, cred);
switch (err) {
case 0:
return err;
case -NFS4ERR_RESOURCE:
/* The IBM lawyers misread another document! */
case -NFS4ERR_DELAY:
err = nfs4_delay(clp->cl_rpcclient, &timeout);
}
} while (err == 0);
return err;
}
struct nfs4_delegreturndata {
struct nfs4_delegreturnargs args;
struct nfs4_delegreturnres res;
@ -5222,20 +5201,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
int status;
unsigned *ptr;
struct nfs4_session *session = clp->cl_session;
long timeout = 0;
int err;
dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
do {
status = _nfs4_proc_create_session(clp);
if (status == -NFS4ERR_DELAY) {
err = nfs4_delay(clp->cl_rpcclient, &timeout);
if (err)
status = err;
}
} while (status == -NFS4ERR_DELAY);
status = _nfs4_proc_create_session(clp);
if (status)
goto out;