Commit 35f5a422 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

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: default avatarChuck Lever <cel@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 02107148
...@@ -177,7 +177,7 @@ nlm_bind_host(struct nlm_host *host) ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment