SUNRPC: new interface to force an RPC rebind
authorChuck Lever <cel@netapp.com>
Tue, 3 Jan 2006 08:55:50 +0000 (09:55 +0100)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 6 Jan 2006 19:58:56 +0000 (14:58 -0500)
 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>
fs/lockd/host.c
include/linux/sunrpc/clnt.h
net/sunrpc/clnt.c

index c4c8601096e03f384160e2c9c923f6793a288735..82f7a0b1d8ae1d563b770e45e62c2fa495d05684 100644 (file)
@@ -177,7 +177,7 @@ nlm_bind_host(struct nlm_host *host)
        if ((clnt = host->h_rpcclnt) != NULL) {
                xprt = clnt->cl_xprt;
                if (time_after_eq(jiffies, host->h_nextrebind)) {
-                       clnt->cl_port = 0;
+                       rpc_force_rebind(clnt);
                        host->h_nextrebind = jiffies + NLM_HOST_REBIND;
                        dprintk("lockd: next rebind in %ld jiffies\n",
                                        host->h_nextrebind - jiffies);
@@ -217,7 +217,7 @@ nlm_rebind_host(struct nlm_host *host)
 {
        dprintk("lockd: rebind host %s\n", host->h_name);
        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;
        }
 }
index b0ab959eca656e0cd3141c823429b0c1fa24eed7..3d605765f84bf6df6c3ab9670e11ba16699d57bf 100644 (file)
@@ -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_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
 size_t         rpc_max_payload(struct rpc_clnt *);
+void           rpc_force_rebind(struct rpc_clnt *);
 int            rpc_ping(struct rpc_clnt *clnt, int flags);
 
 static __inline__
index 25cba94c5683c4fae35aa398088be222dcd29ed6..2789d3083fe7d38e9dcd80c07a0e5f8af42c1646 100644 (file)
@@ -538,6 +538,18 @@ size_t rpc_max_payload(struct rpc_clnt *clnt)
 }
 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
  * exit handler.
@@ -853,8 +865,7 @@ call_connect_status(struct rpc_task *task)
        }
 
        /* Something failed: remote service port may have changed */
-       if (clnt->cl_autobind)
-               clnt->cl_port = 0;
+       rpc_force_rebind(clnt);
 
        switch (status) {
        case -ENOTCONN:
@@ -935,8 +946,7 @@ call_status(struct rpc_task *task)
                break;
        case -ECONNREFUSED:
        case -ENOTCONN:
-               if (clnt->cl_autobind)
-                       clnt->cl_port = 0;
+               rpc_force_rebind(clnt);
                task->tk_action = call_bind;
                break;
        case -EAGAIN:
@@ -995,8 +1005,7 @@ call_timeout(struct rpc_task *task)
                printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
                        clnt->cl_protname, clnt->cl_server);
        }
-       if (clnt->cl_autobind)
-               clnt->cl_port = 0;
+       rpc_force_rebind(clnt);
 
 retry:
        clnt->cl_stats->rpcretrans++;