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:
		
							parent
							
								
									0210714834
								
							
						
					
					
						commit
						35f5a422ce
					
				| @ -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; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -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__ | ||||
|  | ||||
| @ -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++; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user