SUNRPC: new interface to force an RPC rebind
We'd like to hide fields in rpc_xprt and rpc_clnt from upper layer protocols. Start by creating an API to force RPC rebind, replacing logic that simply sets cl_port to zero. Test-plan: Destructive testing (unplugging the network temporarily). Connectathon with UDP and TCP. NFSv2/3 and NFSv4 mounting should be carefully checked. Probably need to rig a server where certain services aren't running, or that returns an error for some typical operation. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Родитель
0210714834
Коммит
35f5a422ce
|
@ -177,7 +177,7 @@ nlm_bind_host(struct nlm_host *host)
|
||||||
if ((clnt = host->h_rpcclnt) != NULL) {
|
if ((clnt = host->h_rpcclnt) != NULL) {
|
||||||
xprt = clnt->cl_xprt;
|
xprt = clnt->cl_xprt;
|
||||||
if (time_after_eq(jiffies, host->h_nextrebind)) {
|
if (time_after_eq(jiffies, host->h_nextrebind)) {
|
||||||
clnt->cl_port = 0;
|
rpc_force_rebind(clnt);
|
||||||
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
|
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
|
||||||
dprintk("lockd: next rebind in %ld jiffies\n",
|
dprintk("lockd: next rebind in %ld jiffies\n",
|
||||||
host->h_nextrebind - jiffies);
|
host->h_nextrebind - jiffies);
|
||||||
|
@ -217,7 +217,7 @@ nlm_rebind_host(struct nlm_host *host)
|
||||||
{
|
{
|
||||||
dprintk("lockd: rebind host %s\n", host->h_name);
|
dprintk("lockd: rebind host %s\n", host->h_name);
|
||||||
if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) {
|
if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) {
|
||||||
host->h_rpcclnt->cl_port = 0;
|
rpc_force_rebind(host->h_rpcclnt);
|
||||||
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
|
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,7 @@ void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
|
||||||
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
|
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
|
||||||
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
|
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
|
||||||
size_t rpc_max_payload(struct rpc_clnt *);
|
size_t rpc_max_payload(struct rpc_clnt *);
|
||||||
|
void rpc_force_rebind(struct rpc_clnt *);
|
||||||
int rpc_ping(struct rpc_clnt *clnt, int flags);
|
int rpc_ping(struct rpc_clnt *clnt, int flags);
|
||||||
|
|
||||||
static __inline__
|
static __inline__
|
||||||
|
|
|
@ -538,6 +538,18 @@ size_t rpc_max_payload(struct rpc_clnt *clnt)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rpc_max_payload);
|
EXPORT_SYMBOL(rpc_max_payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rpc_force_rebind - force transport to check that remote port is unchanged
|
||||||
|
* @clnt: client to rebind
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void rpc_force_rebind(struct rpc_clnt *clnt)
|
||||||
|
{
|
||||||
|
if (clnt->cl_autobind)
|
||||||
|
clnt->cl_port = 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(rpc_force_rebind);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restart an (async) RPC call. Usually called from within the
|
* Restart an (async) RPC call. Usually called from within the
|
||||||
* exit handler.
|
* exit handler.
|
||||||
|
@ -853,8 +865,7 @@ call_connect_status(struct rpc_task *task)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Something failed: remote service port may have changed */
|
/* Something failed: remote service port may have changed */
|
||||||
if (clnt->cl_autobind)
|
rpc_force_rebind(clnt);
|
||||||
clnt->cl_port = 0;
|
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case -ENOTCONN:
|
case -ENOTCONN:
|
||||||
|
@ -935,8 +946,7 @@ call_status(struct rpc_task *task)
|
||||||
break;
|
break;
|
||||||
case -ECONNREFUSED:
|
case -ECONNREFUSED:
|
||||||
case -ENOTCONN:
|
case -ENOTCONN:
|
||||||
if (clnt->cl_autobind)
|
rpc_force_rebind(clnt);
|
||||||
clnt->cl_port = 0;
|
|
||||||
task->tk_action = call_bind;
|
task->tk_action = call_bind;
|
||||||
break;
|
break;
|
||||||
case -EAGAIN:
|
case -EAGAIN:
|
||||||
|
@ -995,8 +1005,7 @@ call_timeout(struct rpc_task *task)
|
||||||
printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
|
printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
|
||||||
clnt->cl_protname, clnt->cl_server);
|
clnt->cl_protname, clnt->cl_server);
|
||||||
}
|
}
|
||||||
if (clnt->cl_autobind)
|
rpc_force_rebind(clnt);
|
||||||
clnt->cl_port = 0;
|
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
clnt->cl_stats->rpcretrans++;
|
clnt->cl_stats->rpcretrans++;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче