diff options
author | Chuck Lever <cel@netapp.com> | 2006-01-03 03:55:50 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-01-06 14:58:56 -0500 |
commit | 35f5a422ce1af836007f811b613c440d0e348e06 (patch) | |
tree | 25aac5cccce27a6ed5ebb4e161f813af2adbaf56 | |
parent | 02107148349f31eee7c0fb06fd7a880df73dbd20 (diff) |
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>
-rw-r--r-- | fs/lockd/host.c | 4 | ||||
-rw-r--r-- | include/linux/sunrpc/clnt.h | 1 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 21 |
3 files changed, 18 insertions, 8 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index c4c8601096e0..82f7a0b1d8ae 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -177,7 +177,7 @@ nlm_bind_host(struct nlm_host *host) | |||
177 | if ((clnt = host->h_rpcclnt) != NULL) { | 177 | if ((clnt = host->h_rpcclnt) != NULL) { |
178 | xprt = clnt->cl_xprt; | 178 | xprt = clnt->cl_xprt; |
179 | if (time_after_eq(jiffies, host->h_nextrebind)) { | 179 | if (time_after_eq(jiffies, host->h_nextrebind)) { |
180 | clnt->cl_port = 0; | 180 | rpc_force_rebind(clnt); |
181 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; | 181 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; |
182 | dprintk("lockd: next rebind in %ld jiffies\n", | 182 | dprintk("lockd: next rebind in %ld jiffies\n", |
183 | host->h_nextrebind - jiffies); | 183 | host->h_nextrebind - jiffies); |
@@ -217,7 +217,7 @@ nlm_rebind_host(struct nlm_host *host) | |||
217 | { | 217 | { |
218 | dprintk("lockd: rebind host %s\n", host->h_name); | 218 | dprintk("lockd: rebind host %s\n", host->h_name); |
219 | if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) { | 219 | if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) { |
220 | host->h_rpcclnt->cl_port = 0; | 220 | rpc_force_rebind(host->h_rpcclnt); |
221 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; | 221 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; |
222 | } | 222 | } |
223 | } | 223 | } |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index b0ab959eca65..3d605765f84b 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -135,6 +135,7 @@ void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset); | |||
135 | void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset); | 135 | void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset); |
136 | void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); | 136 | void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); |
137 | size_t rpc_max_payload(struct rpc_clnt *); | 137 | size_t rpc_max_payload(struct rpc_clnt *); |
138 | void rpc_force_rebind(struct rpc_clnt *); | ||
138 | int rpc_ping(struct rpc_clnt *clnt, int flags); | 139 | int rpc_ping(struct rpc_clnt *clnt, int flags); |
139 | 140 | ||
140 | static __inline__ | 141 | static __inline__ |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 25cba94c5683..2789d3083fe7 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -538,6 +538,18 @@ size_t rpc_max_payload(struct rpc_clnt *clnt) | |||
538 | } | 538 | } |
539 | EXPORT_SYMBOL(rpc_max_payload); | 539 | EXPORT_SYMBOL(rpc_max_payload); |
540 | 540 | ||
541 | /** | ||
542 | * rpc_force_rebind - force transport to check that remote port is unchanged | ||
543 | * @clnt: client to rebind | ||
544 | * | ||
545 | */ | ||
546 | void rpc_force_rebind(struct rpc_clnt *clnt) | ||
547 | { | ||
548 | if (clnt->cl_autobind) | ||
549 | clnt->cl_port = 0; | ||
550 | } | ||
551 | EXPORT_SYMBOL(rpc_force_rebind); | ||
552 | |||
541 | /* | 553 | /* |
542 | * Restart an (async) RPC call. Usually called from within the | 554 | * Restart an (async) RPC call. Usually called from within the |
543 | * exit handler. | 555 | * exit handler. |
@@ -853,8 +865,7 @@ call_connect_status(struct rpc_task *task) | |||
853 | } | 865 | } |
854 | 866 | ||
855 | /* Something failed: remote service port may have changed */ | 867 | /* Something failed: remote service port may have changed */ |
856 | if (clnt->cl_autobind) | 868 | rpc_force_rebind(clnt); |
857 | clnt->cl_port = 0; | ||
858 | 869 | ||
859 | switch (status) { | 870 | switch (status) { |
860 | case -ENOTCONN: | 871 | case -ENOTCONN: |
@@ -935,8 +946,7 @@ call_status(struct rpc_task *task) | |||
935 | break; | 946 | break; |
936 | case -ECONNREFUSED: | 947 | case -ECONNREFUSED: |
937 | case -ENOTCONN: | 948 | case -ENOTCONN: |
938 | if (clnt->cl_autobind) | 949 | rpc_force_rebind(clnt); |
939 | clnt->cl_port = 0; | ||
940 | task->tk_action = call_bind; | 950 | task->tk_action = call_bind; |
941 | break; | 951 | break; |
942 | case -EAGAIN: | 952 | case -EAGAIN: |
@@ -995,8 +1005,7 @@ call_timeout(struct rpc_task *task) | |||
995 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1005 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
996 | clnt->cl_protname, clnt->cl_server); | 1006 | clnt->cl_protname, clnt->cl_server); |
997 | } | 1007 | } |
998 | if (clnt->cl_autobind) | 1008 | rpc_force_rebind(clnt); |
999 | clnt->cl_port = 0; | ||
1000 | 1009 | ||
1001 | retry: | 1010 | retry: |
1002 | clnt->cl_stats->rpcretrans++; | 1011 | clnt->cl_stats->rpcretrans++; |