aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2006-08-22 20:06:15 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-22 23:24:39 -0400
commitec739ef03dc926d05051c8c5838971445504470a (patch)
tree940d3dafd873c159c1279ade15ba11ede1d12983
parent9c5bf38d85a31b946664bcc21078ef5bb10672f7 (diff)
SUNRPC: Create a helper to tell whether a transport is bound
Hide the contents and format of xprt->addr by eliminating direct uses of the xprt->addr.sin_port field. This change is required to support alternate RPC host address formats (eg IPv6). Test-plan: Destructive testing (unplugging the network temporarily). Repeated runs of Connectathon locking suite with UDP and TCP. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--include/linux/sunrpc/xprt.h16
-rw-r--r--net/sunrpc/clnt.c10
-rw-r--r--net/sunrpc/pmap_clnt.c5
-rw-r--r--net/sunrpc/xprt.c2
-rw-r--r--net/sunrpc/xprtsock.c14
5 files changed, 36 insertions, 11 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 3a0cca255b76..a71106723d71 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -269,6 +269,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
269#define XPRT_CONNECTED (1) 269#define XPRT_CONNECTED (1)
270#define XPRT_CONNECTING (2) 270#define XPRT_CONNECTING (2)
271#define XPRT_CLOSE_WAIT (3) 271#define XPRT_CLOSE_WAIT (3)
272#define XPRT_BOUND (4)
272 273
273static inline void xprt_set_connected(struct rpc_xprt *xprt) 274static inline void xprt_set_connected(struct rpc_xprt *xprt)
274{ 275{
@@ -312,6 +313,21 @@ static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt)
312 return test_and_set_bit(XPRT_CONNECTING, &xprt->state); 313 return test_and_set_bit(XPRT_CONNECTING, &xprt->state);
313} 314}
314 315
316static inline void xprt_set_bound(struct rpc_xprt *xprt)
317{
318 test_and_set_bit(XPRT_BOUND, &xprt->state);
319}
320
321static inline int xprt_bound(struct rpc_xprt *xprt)
322{
323 return test_bit(XPRT_BOUND, &xprt->state);
324}
325
326static inline void xprt_clear_bound(struct rpc_xprt *xprt)
327{
328 clear_bit(XPRT_BOUND, &xprt->state);
329}
330
315#endif /* __KERNEL__*/ 331#endif /* __KERNEL__*/
316 332
317#endif /* _LINUX_SUNRPC_XPRT_H */ 333#endif /* _LINUX_SUNRPC_XPRT_H */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 3e19d321067a..0b8d03d08561 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -148,7 +148,6 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
148 clnt->cl_maxproc = version->nrprocs; 148 clnt->cl_maxproc = version->nrprocs;
149 clnt->cl_protname = program->name; 149 clnt->cl_protname = program->name;
150 clnt->cl_pmap = &clnt->cl_pmap_default; 150 clnt->cl_pmap = &clnt->cl_pmap_default;
151 clnt->cl_port = xprt->addr.sin_port;
152 clnt->cl_prog = program->number; 151 clnt->cl_prog = program->number;
153 clnt->cl_vers = version->number; 152 clnt->cl_vers = version->number;
154 clnt->cl_prot = xprt->prot; 153 clnt->cl_prot = xprt->prot;
@@ -156,7 +155,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
156 clnt->cl_metrics = rpc_alloc_iostats(clnt); 155 clnt->cl_metrics = rpc_alloc_iostats(clnt);
157 rpc_init_wait_queue(&clnt->cl_pmap_default.pm_bindwait, "bindwait"); 156 rpc_init_wait_queue(&clnt->cl_pmap_default.pm_bindwait, "bindwait");
158 157
159 if (!clnt->cl_port) 158 if (!xprt_bound(clnt->cl_xprt))
160 clnt->cl_autobind = 1; 159 clnt->cl_autobind = 1;
161 160
162 clnt->cl_rtt = &clnt->cl_rtt_default; 161 clnt->cl_rtt = &clnt->cl_rtt_default;
@@ -570,7 +569,7 @@ EXPORT_SYMBOL(rpc_max_payload);
570void rpc_force_rebind(struct rpc_clnt *clnt) 569void rpc_force_rebind(struct rpc_clnt *clnt)
571{ 570{
572 if (clnt->cl_autobind) 571 if (clnt->cl_autobind)
573 clnt->cl_port = 0; 572 xprt_clear_bound(clnt->cl_xprt);
574} 573}
575EXPORT_SYMBOL(rpc_force_rebind); 574EXPORT_SYMBOL(rpc_force_rebind);
576 575
@@ -782,14 +781,15 @@ static void
782call_bind(struct rpc_task *task) 781call_bind(struct rpc_task *task)
783{ 782{
784 struct rpc_clnt *clnt = task->tk_client; 783 struct rpc_clnt *clnt = task->tk_client;
784 struct rpc_xprt *xprt = task->tk_xprt;
785 785
786 dprintk("RPC: %4d call_bind (status %d)\n", 786 dprintk("RPC: %4d call_bind (status %d)\n",
787 task->tk_pid, task->tk_status); 787 task->tk_pid, task->tk_status);
788 788
789 task->tk_action = call_connect; 789 task->tk_action = call_connect;
790 if (!clnt->cl_port) { 790 if (!xprt_bound(xprt)) {
791 task->tk_action = call_bind_status; 791 task->tk_action = call_bind_status;
792 task->tk_timeout = task->tk_xprt->bind_timeout; 792 task->tk_timeout = xprt->bind_timeout;
793 rpc_getport(task, clnt); 793 rpc_getport(task, clnt);
794 } 794 }
795} 795}
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 623180f224c9..209ffdfee10b 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -142,15 +142,17 @@ pmap_getport_done(struct rpc_task *task)
142 dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n", 142 dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n",
143 task->tk_pid, task->tk_status, clnt->cl_port); 143 task->tk_pid, task->tk_status, clnt->cl_port);
144 144
145 xprt->ops->set_port(xprt, 0);
146 if (task->tk_status < 0) { 145 if (task->tk_status < 0) {
147 /* Make the calling task exit with an error */ 146 /* Make the calling task exit with an error */
147 xprt->ops->set_port(xprt, 0);
148 task->tk_action = rpc_exit_task; 148 task->tk_action = rpc_exit_task;
149 } else if (clnt->cl_port == 0) { 149 } else if (clnt->cl_port == 0) {
150 /* Program not registered */ 150 /* Program not registered */
151 xprt->ops->set_port(xprt, 0);
151 rpc_exit(task, -EACCES); 152 rpc_exit(task, -EACCES);
152 } else { 153 } else {
153 xprt->ops->set_port(xprt, clnt->cl_port); 154 xprt->ops->set_port(xprt, clnt->cl_port);
155 xprt_set_bound(xprt);
154 clnt->cl_port = htons(clnt->cl_port); 156 clnt->cl_port = htons(clnt->cl_port);
155 } 157 }
156 spin_lock(&pmap_lock); 158 spin_lock(&pmap_lock);
@@ -218,6 +220,7 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileg
218 if (IS_ERR(xprt)) 220 if (IS_ERR(xprt))
219 return (struct rpc_clnt *)xprt; 221 return (struct rpc_clnt *)xprt;
220 xprt->ops->set_port(xprt, RPC_PMAP_PORT); 222 xprt->ops->set_port(xprt, RPC_PMAP_PORT);
223 xprt_set_bound(xprt);
221 if (!privileged) 224 if (!privileged)
222 xprt->resvport = 0; 225 xprt->resvport = 0;
223 226
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index e8c2bc4977f3..e239ef985ef7 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -534,7 +534,7 @@ void xprt_connect(struct rpc_task *task)
534 dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid, 534 dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid,
535 xprt, (xprt_connected(xprt) ? "is" : "is not")); 535 xprt, (xprt_connected(xprt) ? "is" : "is not"));
536 536
537 if (!xprt->addr.sin_port) { 537 if (!xprt_bound(xprt)) {
538 task->tk_status = -EIO; 538 task->tk_status = -EIO;
539 return; 539 return;
540 } 540 }
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 441bd53f5eca..123ac1e5ba15 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1016,7 +1016,7 @@ static void xs_udp_connect_worker(void *args)
1016 struct socket *sock = xprt->sock; 1016 struct socket *sock = xprt->sock;
1017 int err, status = -EIO; 1017 int err, status = -EIO;
1018 1018
1019 if (xprt->shutdown || xprt->addr.sin_port == 0) 1019 if (xprt->shutdown || !xprt_bound(xprt))
1020 goto out; 1020 goto out;
1021 1021
1022 dprintk("RPC: xs_udp_connect_worker for xprt %p\n", xprt); 1022 dprintk("RPC: xs_udp_connect_worker for xprt %p\n", xprt);
@@ -1099,7 +1099,7 @@ static void xs_tcp_connect_worker(void *args)
1099 struct socket *sock = xprt->sock; 1099 struct socket *sock = xprt->sock;
1100 int err, status = -EIO; 1100 int err, status = -EIO;
1101 1101
1102 if (xprt->shutdown || xprt->addr.sin_port == 0) 1102 if (xprt->shutdown || !xprt_bound(xprt))
1103 goto out; 1103 goto out;
1104 1104
1105 dprintk("RPC: xs_tcp_connect_worker for xprt %p\n", xprt); 1105 dprintk("RPC: xs_tcp_connect_worker for xprt %p\n", xprt);
@@ -1307,8 +1307,11 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
1307 if (xprt->slot == NULL) 1307 if (xprt->slot == NULL)
1308 return -ENOMEM; 1308 return -ENOMEM;
1309 1309
1310 xprt->prot = IPPROTO_UDP; 1310 if (ntohs(xprt->addr.sin_port) != 0)
1311 xprt_set_bound(xprt);
1311 xprt->port = xs_get_random_port(); 1312 xprt->port = xs_get_random_port();
1313
1314 xprt->prot = IPPROTO_UDP;
1312 xprt->tsh_size = 0; 1315 xprt->tsh_size = 0;
1313 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; 1316 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
1314 /* XXX: header size can vary due to auth type, IPv6, etc. */ 1317 /* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1348,8 +1351,11 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
1348 if (xprt->slot == NULL) 1351 if (xprt->slot == NULL)
1349 return -ENOMEM; 1352 return -ENOMEM;
1350 1353
1351 xprt->prot = IPPROTO_TCP; 1354 if (ntohs(xprt->addr.sin_port) != 0)
1355 xprt_set_bound(xprt);
1352 xprt->port = xs_get_random_port(); 1356 xprt->port = xs_get_random_port();
1357
1358 xprt->prot = IPPROTO_TCP;
1353 xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); 1359 xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
1354 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; 1360 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
1355 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; 1361 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;