diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2006-08-22 20:06:15 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-22 23:24:39 -0400 |
commit | ec739ef03dc926d05051c8c5838971445504470a (patch) | |
tree | 940d3dafd873c159c1279ade15ba11ede1d12983 | |
parent | 9c5bf38d85a31b946664bcc21078ef5bb10672f7 (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.h | 16 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 10 | ||||
-rw-r--r-- | net/sunrpc/pmap_clnt.c | 5 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 14 |
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 | ||
273 | static inline void xprt_set_connected(struct rpc_xprt *xprt) | 274 | static 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 | ||
316 | static inline void xprt_set_bound(struct rpc_xprt *xprt) | ||
317 | { | ||
318 | test_and_set_bit(XPRT_BOUND, &xprt->state); | ||
319 | } | ||
320 | |||
321 | static inline int xprt_bound(struct rpc_xprt *xprt) | ||
322 | { | ||
323 | return test_bit(XPRT_BOUND, &xprt->state); | ||
324 | } | ||
325 | |||
326 | static 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); | |||
570 | void rpc_force_rebind(struct rpc_clnt *clnt) | 569 | void 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 | } |
575 | EXPORT_SYMBOL(rpc_force_rebind); | 574 | EXPORT_SYMBOL(rpc_force_rebind); |
576 | 575 | ||
@@ -782,14 +781,15 @@ static void | |||
782 | call_bind(struct rpc_task *task) | 781 | call_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; |