diff options
author | David Howells <dhowells@redhat.com> | 2016-06-17 05:06:56 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-06-22 09:00:23 -0400 |
commit | aa390bbe2113dd0de99cf35c39d7701d4412b744 (patch) | |
tree | fd836f0bacb921ec94909a03ae801e5db855549b | |
parent | 999b69f89241c9384c104b84329c13350fd696ef (diff) |
rxrpc: Kill off the rxrpc_transport struct
The rxrpc_transport struct is now redundant, given that the rxrpc_peer
struct is now per peer port rather than per peer host, so get rid of it.
Service connection lists are transferred to the rxrpc_peer struct, as is
the conn_lock. Previous patches moved the client connection handling out
of the rxrpc_transport struct and discarded the connection bundling code.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | net/rxrpc/Makefile | 1 | ||||
-rw-r--r-- | net/rxrpc/af_rxrpc.c | 46 | ||||
-rw-r--r-- | net/rxrpc/ar-internal.h | 57 | ||||
-rw-r--r-- | net/rxrpc/call_accept.c | 11 | ||||
-rw-r--r-- | net/rxrpc/call_object.c | 16 | ||||
-rw-r--r-- | net/rxrpc/conn_object.c | 78 | ||||
-rw-r--r-- | net/rxrpc/input.c | 8 | ||||
-rw-r--r-- | net/rxrpc/output.c | 24 | ||||
-rw-r--r-- | net/rxrpc/peer_object.c | 2 | ||||
-rw-r--r-- | net/rxrpc/sysctl.c | 8 | ||||
-rw-r--r-- | net/rxrpc/transport.c | 265 |
11 files changed, 65 insertions, 451 deletions
diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index cfa221536f33..6522e50fb750 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile | |||
@@ -22,7 +22,6 @@ af-rxrpc-y := \ | |||
22 | recvmsg.o \ | 22 | recvmsg.o \ |
23 | security.o \ | 23 | security.o \ |
24 | skbuff.o \ | 24 | skbuff.o \ |
25 | transport.o \ | ||
26 | utils.o | 25 | utils.o |
27 | 26 | ||
28 | af-rxrpc-$(CONFIG_PROC_FS) += proc.o | 27 | af-rxrpc-$(CONFIG_PROC_FS) += proc.o |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index f3b6ed8196c3..5d3e795a7c48 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -224,37 +224,6 @@ static int rxrpc_listen(struct socket *sock, int backlog) | |||
224 | return ret; | 224 | return ret; |
225 | } | 225 | } |
226 | 226 | ||
227 | /* | ||
228 | * find a transport by address | ||
229 | */ | ||
230 | struct rxrpc_transport * | ||
231 | rxrpc_name_to_transport(struct rxrpc_conn_parameters *cp, | ||
232 | struct sockaddr *addr, | ||
233 | int addr_len, | ||
234 | gfp_t gfp) | ||
235 | { | ||
236 | struct sockaddr_rxrpc *srx = (struct sockaddr_rxrpc *) addr; | ||
237 | struct rxrpc_transport *trans; | ||
238 | |||
239 | _enter("%p,%d", addr, addr_len); | ||
240 | |||
241 | if (cp->local->srx.transport_type != srx->transport_type) | ||
242 | return ERR_PTR(-ESOCKTNOSUPPORT); | ||
243 | if (cp->local->srx.transport.family != srx->transport.family) | ||
244 | return ERR_PTR(-EAFNOSUPPORT); | ||
245 | |||
246 | /* find a remote transport endpoint from the local one */ | ||
247 | cp->peer = rxrpc_lookup_peer(cp->local, srx, gfp); | ||
248 | if (!cp->peer) | ||
249 | return ERR_PTR(-ENOMEM); | ||
250 | |||
251 | /* find a transport */ | ||
252 | trans = rxrpc_get_transport(cp->local, cp->peer, gfp); | ||
253 | rxrpc_put_peer(cp->peer); | ||
254 | _leave(" = %p", trans); | ||
255 | return trans; | ||
256 | } | ||
257 | |||
258 | /** | 227 | /** |
259 | * rxrpc_kernel_begin_call - Allow a kernel service to begin a call | 228 | * rxrpc_kernel_begin_call - Allow a kernel service to begin a call |
260 | * @sock: The socket on which to make the call | 229 | * @sock: The socket on which to make the call |
@@ -276,7 +245,6 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, | |||
276 | gfp_t gfp) | 245 | gfp_t gfp) |
277 | { | 246 | { |
278 | struct rxrpc_conn_parameters cp; | 247 | struct rxrpc_conn_parameters cp; |
279 | struct rxrpc_transport *trans; | ||
280 | struct rxrpc_call *call; | 248 | struct rxrpc_call *call; |
281 | struct rxrpc_sock *rx = rxrpc_sk(sock->sk); | 249 | struct rxrpc_sock *rx = rxrpc_sk(sock->sk); |
282 | int ret; | 250 | int ret; |
@@ -300,19 +268,8 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, | |||
300 | cp.security_level = 0; | 268 | cp.security_level = 0; |
301 | cp.exclusive = false; | 269 | cp.exclusive = false; |
302 | cp.service_id = srx->srx_service; | 270 | cp.service_id = srx->srx_service; |
271 | call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, gfp); | ||
303 | 272 | ||
304 | trans = rxrpc_name_to_transport(&cp, (struct sockaddr *)srx, | ||
305 | sizeof(*srx), gfp); | ||
306 | if (IS_ERR(trans)) { | ||
307 | call = ERR_CAST(trans); | ||
308 | trans = NULL; | ||
309 | goto out_notrans; | ||
310 | } | ||
311 | cp.peer = trans->peer; | ||
312 | |||
313 | call = rxrpc_new_client_call(rx, &cp, trans, srx, user_call_ID, gfp); | ||
314 | rxrpc_put_transport(trans); | ||
315 | out_notrans: | ||
316 | release_sock(&rx->sk); | 273 | release_sock(&rx->sk); |
317 | _leave(" = %p", call); | 274 | _leave(" = %p", call); |
318 | return call; | 275 | return call; |
@@ -831,7 +788,6 @@ static void __exit af_rxrpc_exit(void) | |||
831 | proto_unregister(&rxrpc_proto); | 788 | proto_unregister(&rxrpc_proto); |
832 | rxrpc_destroy_all_calls(); | 789 | rxrpc_destroy_all_calls(); |
833 | rxrpc_destroy_all_connections(); | 790 | rxrpc_destroy_all_connections(); |
834 | rxrpc_destroy_all_transports(); | ||
835 | 791 | ||
836 | ASSERTCMP(atomic_read(&rxrpc_n_skbs), ==, 0); | 792 | ASSERTCMP(atomic_read(&rxrpc_n_skbs), ==, 0); |
837 | 793 | ||
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 26fe137d62bb..702db72196fb 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -207,6 +207,8 @@ struct rxrpc_peer { | |||
207 | struct rxrpc_local *local; | 207 | struct rxrpc_local *local; |
208 | struct hlist_head error_targets; /* targets for net error distribution */ | 208 | struct hlist_head error_targets; /* targets for net error distribution */ |
209 | struct work_struct error_distributor; | 209 | struct work_struct error_distributor; |
210 | struct rb_root service_conns; /* Service connections */ | ||
211 | rwlock_t conn_lock; | ||
210 | spinlock_t lock; /* access lock */ | 212 | spinlock_t lock; /* access lock */ |
211 | unsigned int if_mtu; /* interface MTU for this peer */ | 213 | unsigned int if_mtu; /* interface MTU for this peer */ |
212 | unsigned int mtu; /* network MTU for this peer */ | 214 | unsigned int mtu; /* network MTU for this peer */ |
@@ -226,22 +228,6 @@ struct rxrpc_peer { | |||
226 | }; | 228 | }; |
227 | 229 | ||
228 | /* | 230 | /* |
229 | * RxRPC point-to-point transport / connection manager definition | ||
230 | * - handles a bundle of connections between two endpoints | ||
231 | * - matched by { local, peer } | ||
232 | */ | ||
233 | struct rxrpc_transport { | ||
234 | struct rxrpc_local *local; /* local transport endpoint */ | ||
235 | struct rxrpc_peer *peer; /* remote transport endpoint */ | ||
236 | struct rb_root server_conns; /* server connections on this transport */ | ||
237 | struct list_head link; /* link in master session list */ | ||
238 | unsigned long put_time; /* time at which to reap */ | ||
239 | rwlock_t conn_lock; /* lock for active/dead connections */ | ||
240 | atomic_t usage; | ||
241 | int debug_id; /* debug ID for printks */ | ||
242 | }; | ||
243 | |||
244 | /* | ||
245 | * Keys for matching a connection. | 231 | * Keys for matching a connection. |
246 | */ | 232 | */ |
247 | struct rxrpc_conn_proto { | 233 | struct rxrpc_conn_proto { |
@@ -271,11 +257,10 @@ struct rxrpc_conn_parameters { | |||
271 | 257 | ||
272 | /* | 258 | /* |
273 | * RxRPC connection definition | 259 | * RxRPC connection definition |
274 | * - matched by { transport, service_id, conn_id, direction, key } | 260 | * - matched by { local, peer, epoch, conn_id, direction } |
275 | * - each connection can only handle four simultaneous calls | 261 | * - each connection can only handle four simultaneous calls |
276 | */ | 262 | */ |
277 | struct rxrpc_connection { | 263 | struct rxrpc_connection { |
278 | struct rxrpc_transport *trans; /* transport session */ | ||
279 | struct rxrpc_conn_proto proto; | 264 | struct rxrpc_conn_proto proto; |
280 | struct rxrpc_conn_parameters params; | 265 | struct rxrpc_conn_parameters params; |
281 | 266 | ||
@@ -286,7 +271,7 @@ struct rxrpc_connection { | |||
286 | struct work_struct processor; /* connection event processor */ | 271 | struct work_struct processor; /* connection event processor */ |
287 | union { | 272 | union { |
288 | struct rb_node client_node; /* Node in local->client_conns */ | 273 | struct rb_node client_node; /* Node in local->client_conns */ |
289 | struct rb_node service_node; /* Node in trans->server_conns */ | 274 | struct rb_node service_node; /* Node in peer->service_conns */ |
290 | }; | 275 | }; |
291 | struct list_head link; /* link in master connection list */ | 276 | struct list_head link; /* link in master connection list */ |
292 | struct rb_root calls; /* calls on this connection */ | 277 | struct rb_root calls; /* calls on this connection */ |
@@ -494,10 +479,6 @@ extern u32 rxrpc_epoch; | |||
494 | extern atomic_t rxrpc_debug_id; | 479 | extern atomic_t rxrpc_debug_id; |
495 | extern struct workqueue_struct *rxrpc_workqueue; | 480 | extern struct workqueue_struct *rxrpc_workqueue; |
496 | 481 | ||
497 | extern struct rxrpc_transport *rxrpc_name_to_transport(struct rxrpc_conn_parameters *, | ||
498 | struct sockaddr *, | ||
499 | int, gfp_t); | ||
500 | |||
501 | /* | 482 | /* |
502 | * call_accept.c | 483 | * call_accept.c |
503 | */ | 484 | */ |
@@ -526,7 +507,6 @@ struct rxrpc_call *rxrpc_find_call_hash(struct rxrpc_host_header *, | |||
526 | struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *, unsigned long); | 507 | struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *, unsigned long); |
527 | struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *, | 508 | struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *, |
528 | struct rxrpc_conn_parameters *, | 509 | struct rxrpc_conn_parameters *, |
529 | struct rxrpc_transport *, | ||
530 | struct sockaddr_rxrpc *, | 510 | struct sockaddr_rxrpc *, |
531 | unsigned long, gfp_t); | 511 | unsigned long, gfp_t); |
532 | struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *, | 512 | struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *, |
@@ -560,15 +540,16 @@ extern struct list_head rxrpc_connections; | |||
560 | extern rwlock_t rxrpc_connection_lock; | 540 | extern rwlock_t rxrpc_connection_lock; |
561 | 541 | ||
562 | int rxrpc_connect_call(struct rxrpc_call *, struct rxrpc_conn_parameters *, | 542 | int rxrpc_connect_call(struct rxrpc_call *, struct rxrpc_conn_parameters *, |
563 | struct rxrpc_transport *, | ||
564 | struct sockaddr_rxrpc *, gfp_t); | 543 | struct sockaddr_rxrpc *, gfp_t); |
544 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *, | ||
545 | struct rxrpc_peer *, | ||
546 | struct sk_buff *); | ||
565 | void rxrpc_disconnect_call(struct rxrpc_call *); | 547 | void rxrpc_disconnect_call(struct rxrpc_call *); |
566 | void rxrpc_put_connection(struct rxrpc_connection *); | 548 | void rxrpc_put_connection(struct rxrpc_connection *); |
567 | void __exit rxrpc_destroy_all_connections(void); | 549 | void __exit rxrpc_destroy_all_connections(void); |
568 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_transport *, | 550 | struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *, |
569 | struct sk_buff *); | 551 | struct rxrpc_peer *, |
570 | extern struct rxrpc_connection * | 552 | struct sk_buff *); |
571 | rxrpc_incoming_connection(struct rxrpc_transport *, struct sk_buff *); | ||
572 | 553 | ||
573 | static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn) | 554 | static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn) |
574 | { | 555 | { |
@@ -585,12 +566,6 @@ static inline void rxrpc_get_connection(struct rxrpc_connection *conn) | |||
585 | atomic_inc(&conn->usage); | 566 | atomic_inc(&conn->usage); |
586 | } | 567 | } |
587 | 568 | ||
588 | static inline | ||
589 | struct rxrpc_connection *rxrpc_get_connection_maybe(struct rxrpc_connection *conn) | ||
590 | { | ||
591 | return atomic_inc_not_zero(&conn->usage) ? conn : NULL; | ||
592 | } | ||
593 | |||
594 | /* | 569 | /* |
595 | * input.c | 570 | * input.c |
596 | */ | 571 | */ |
@@ -745,18 +720,6 @@ static inline void rxrpc_sysctl_exit(void) {} | |||
745 | #endif | 720 | #endif |
746 | 721 | ||
747 | /* | 722 | /* |
748 | * transport.c | ||
749 | */ | ||
750 | extern unsigned int rxrpc_transport_expiry; | ||
751 | |||
752 | struct rxrpc_transport *rxrpc_get_transport(struct rxrpc_local *, | ||
753 | struct rxrpc_peer *, gfp_t); | ||
754 | void rxrpc_put_transport(struct rxrpc_transport *); | ||
755 | void __exit rxrpc_destroy_all_transports(void); | ||
756 | struct rxrpc_transport *rxrpc_find_transport(struct rxrpc_local *, | ||
757 | struct rxrpc_peer *); | ||
758 | |||
759 | /* | ||
760 | * utils.c | 723 | * utils.c |
761 | */ | 724 | */ |
762 | void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *, | 725 | void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *, |
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c index 833ad0622b61..202e053a3c6d 100644 --- a/net/rxrpc/call_accept.c +++ b/net/rxrpc/call_accept.c | |||
@@ -74,7 +74,6 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, | |||
74 | struct sockaddr_rxrpc *srx) | 74 | struct sockaddr_rxrpc *srx) |
75 | { | 75 | { |
76 | struct rxrpc_connection *conn; | 76 | struct rxrpc_connection *conn; |
77 | struct rxrpc_transport *trans; | ||
78 | struct rxrpc_skb_priv *sp, *nsp; | 77 | struct rxrpc_skb_priv *sp, *nsp; |
79 | struct rxrpc_peer *peer; | 78 | struct rxrpc_peer *peer; |
80 | struct rxrpc_call *call; | 79 | struct rxrpc_call *call; |
@@ -102,16 +101,8 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, | |||
102 | goto error; | 101 | goto error; |
103 | } | 102 | } |
104 | 103 | ||
105 | trans = rxrpc_get_transport(local, peer, GFP_NOIO); | 104 | conn = rxrpc_incoming_connection(local, peer, skb); |
106 | rxrpc_put_peer(peer); | 105 | rxrpc_put_peer(peer); |
107 | if (IS_ERR(trans)) { | ||
108 | _debug("no trans"); | ||
109 | ret = -EBUSY; | ||
110 | goto error; | ||
111 | } | ||
112 | |||
113 | conn = rxrpc_incoming_connection(trans, skb); | ||
114 | rxrpc_put_transport(trans); | ||
115 | if (IS_ERR(conn)) { | 106 | if (IS_ERR(conn)) { |
116 | _debug("no conn"); | 107 | _debug("no conn"); |
117 | ret = PTR_ERR(conn); | 108 | ret = PTR_ERR(conn); |
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 9b3b48abe12f..ad933daae13b 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c | |||
@@ -286,11 +286,9 @@ static struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp) | |||
286 | /* | 286 | /* |
287 | * Allocate a new client call. | 287 | * Allocate a new client call. |
288 | */ | 288 | */ |
289 | static struct rxrpc_call *rxrpc_alloc_client_call( | 289 | static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, |
290 | struct rxrpc_sock *rx, | 290 | struct sockaddr_rxrpc *srx, |
291 | struct rxrpc_conn_parameters *cp, | 291 | gfp_t gfp) |
292 | struct sockaddr_rxrpc *srx, | ||
293 | gfp_t gfp) | ||
294 | { | 292 | { |
295 | struct rxrpc_call *call; | 293 | struct rxrpc_call *call; |
296 | 294 | ||
@@ -333,7 +331,6 @@ static struct rxrpc_call *rxrpc_alloc_client_call( | |||
333 | */ | 331 | */ |
334 | static int rxrpc_begin_client_call(struct rxrpc_call *call, | 332 | static int rxrpc_begin_client_call(struct rxrpc_call *call, |
335 | struct rxrpc_conn_parameters *cp, | 333 | struct rxrpc_conn_parameters *cp, |
336 | struct rxrpc_transport *trans, | ||
337 | struct sockaddr_rxrpc *srx, | 334 | struct sockaddr_rxrpc *srx, |
338 | gfp_t gfp) | 335 | gfp_t gfp) |
339 | { | 336 | { |
@@ -342,7 +339,7 @@ static int rxrpc_begin_client_call(struct rxrpc_call *call, | |||
342 | /* Set up or get a connection record and set the protocol parameters, | 339 | /* Set up or get a connection record and set the protocol parameters, |
343 | * including channel number and call ID. | 340 | * including channel number and call ID. |
344 | */ | 341 | */ |
345 | ret = rxrpc_connect_call(call, cp, trans, srx, gfp); | 342 | ret = rxrpc_connect_call(call, cp, srx, gfp); |
346 | if (ret < 0) | 343 | if (ret < 0) |
347 | return ret; | 344 | return ret; |
348 | 345 | ||
@@ -366,7 +363,6 @@ static int rxrpc_begin_client_call(struct rxrpc_call *call, | |||
366 | */ | 363 | */ |
367 | struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, | 364 | struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, |
368 | struct rxrpc_conn_parameters *cp, | 365 | struct rxrpc_conn_parameters *cp, |
369 | struct rxrpc_transport *trans, | ||
370 | struct sockaddr_rxrpc *srx, | 366 | struct sockaddr_rxrpc *srx, |
371 | unsigned long user_call_ID, | 367 | unsigned long user_call_ID, |
372 | gfp_t gfp) | 368 | gfp_t gfp) |
@@ -377,7 +373,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, | |||
377 | 373 | ||
378 | _enter("%p,%lx", rx, user_call_ID); | 374 | _enter("%p,%lx", rx, user_call_ID); |
379 | 375 | ||
380 | call = rxrpc_alloc_client_call(rx, cp, srx, gfp); | 376 | call = rxrpc_alloc_client_call(rx, srx, gfp); |
381 | if (IS_ERR(call)) { | 377 | if (IS_ERR(call)) { |
382 | _leave(" = %ld", PTR_ERR(call)); | 378 | _leave(" = %ld", PTR_ERR(call)); |
383 | return call; | 379 | return call; |
@@ -413,7 +409,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, | |||
413 | list_add_tail(&call->link, &rxrpc_calls); | 409 | list_add_tail(&call->link, &rxrpc_calls); |
414 | write_unlock_bh(&rxrpc_call_lock); | 410 | write_unlock_bh(&rxrpc_call_lock); |
415 | 411 | ||
416 | ret = rxrpc_begin_client_call(call, cp, trans, srx, gfp); | 412 | ret = rxrpc_begin_client_call(call, cp, srx, gfp); |
417 | if (ret < 0) | 413 | if (ret < 0) |
418 | goto error; | 414 | goto error; |
419 | 415 | ||
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index 276ff505394f..4bfad7cf96cb 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c | |||
@@ -100,9 +100,7 @@ static void rxrpc_add_call_ID_to_conn(struct rxrpc_connection *conn, | |||
100 | * padding bytes in *cp. | 100 | * padding bytes in *cp. |
101 | */ | 101 | */ |
102 | static struct rxrpc_connection * | 102 | static struct rxrpc_connection * |
103 | rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, | 103 | rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, gfp_t gfp) |
104 | struct rxrpc_transport *trans, | ||
105 | gfp_t gfp) | ||
106 | { | 104 | { |
107 | struct rxrpc_connection *conn; | 105 | struct rxrpc_connection *conn; |
108 | int ret; | 106 | int ret; |
@@ -146,9 +144,10 @@ rxrpc_alloc_client_connection(struct rxrpc_conn_parameters *cp, | |||
146 | list_add_tail(&conn->link, &rxrpc_connections); | 144 | list_add_tail(&conn->link, &rxrpc_connections); |
147 | write_unlock(&rxrpc_connection_lock); | 145 | write_unlock(&rxrpc_connection_lock); |
148 | 146 | ||
147 | /* We steal the caller's peer ref. */ | ||
148 | cp->peer = NULL; | ||
149 | rxrpc_get_local(conn->params.local); | ||
149 | key_get(conn->params.key); | 150 | key_get(conn->params.key); |
150 | conn->trans = trans; | ||
151 | atomic_inc(&trans->usage); | ||
152 | 151 | ||
153 | _leave(" = %p", conn); | 152 | _leave(" = %p", conn); |
154 | return conn; | 153 | return conn; |
@@ -167,7 +166,6 @@ error_0: | |||
167 | */ | 166 | */ |
168 | int rxrpc_connect_call(struct rxrpc_call *call, | 167 | int rxrpc_connect_call(struct rxrpc_call *call, |
169 | struct rxrpc_conn_parameters *cp, | 168 | struct rxrpc_conn_parameters *cp, |
170 | struct rxrpc_transport *trans, | ||
171 | struct sockaddr_rxrpc *srx, | 169 | struct sockaddr_rxrpc *srx, |
172 | gfp_t gfp) | 170 | gfp_t gfp) |
173 | { | 171 | { |
@@ -181,8 +179,9 @@ int rxrpc_connect_call(struct rxrpc_call *call, | |||
181 | 179 | ||
182 | _enter("{%d,%lx},", call->debug_id, call->user_call_ID); | 180 | _enter("{%d,%lx},", call->debug_id, call->user_call_ID); |
183 | 181 | ||
184 | cp->peer = trans->peer; | 182 | cp->peer = rxrpc_lookup_peer(cp->local, srx, gfp); |
185 | rxrpc_get_peer(cp->peer); | 183 | if (!cp->peer) |
184 | return -ENOMEM; | ||
186 | 185 | ||
187 | if (!cp->exclusive) { | 186 | if (!cp->exclusive) { |
188 | /* Search for a existing client connection unless this is going | 187 | /* Search for a existing client connection unless this is going |
@@ -210,7 +209,7 @@ int rxrpc_connect_call(struct rxrpc_call *call, | |||
210 | 209 | ||
211 | /* We didn't find a connection or we want an exclusive one. */ | 210 | /* We didn't find a connection or we want an exclusive one. */ |
212 | _debug("get new conn"); | 211 | _debug("get new conn"); |
213 | candidate = rxrpc_alloc_client_connection(cp, trans, gfp); | 212 | candidate = rxrpc_alloc_client_connection(cp, gfp); |
214 | if (!candidate) { | 213 | if (!candidate) { |
215 | _leave(" = -ENOMEM"); | 214 | _leave(" = -ENOMEM"); |
216 | return -ENOMEM; | 215 | return -ENOMEM; |
@@ -281,6 +280,8 @@ found_channel: | |||
281 | 280 | ||
282 | rxrpc_add_call_ID_to_conn(conn, call); | 281 | rxrpc_add_call_ID_to_conn(conn, call); |
283 | spin_unlock(&conn->channel_lock); | 282 | spin_unlock(&conn->channel_lock); |
283 | rxrpc_put_peer(cp->peer); | ||
284 | cp->peer = NULL; | ||
284 | _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage)); | 285 | _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage)); |
285 | return 0; | 286 | return 0; |
286 | 287 | ||
@@ -329,6 +330,8 @@ interrupted: | |||
329 | remove_wait_queue(&conn->channel_wq, &myself); | 330 | remove_wait_queue(&conn->channel_wq, &myself); |
330 | __set_current_state(TASK_RUNNING); | 331 | __set_current_state(TASK_RUNNING); |
331 | rxrpc_put_connection(conn); | 332 | rxrpc_put_connection(conn); |
333 | rxrpc_put_peer(cp->peer); | ||
334 | cp->peer = NULL; | ||
332 | _leave(" = -ERESTARTSYS"); | 335 | _leave(" = -ERESTARTSYS"); |
333 | return -ERESTARTSYS; | 336 | return -ERESTARTSYS; |
334 | } | 337 | } |
@@ -336,7 +339,8 @@ interrupted: | |||
336 | /* | 339 | /* |
337 | * get a record of an incoming connection | 340 | * get a record of an incoming connection |
338 | */ | 341 | */ |
339 | struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_transport *trans, | 342 | struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *local, |
343 | struct rxrpc_peer *peer, | ||
340 | struct sk_buff *skb) | 344 | struct sk_buff *skb) |
341 | { | 345 | { |
342 | struct rxrpc_connection *conn, *candidate = NULL; | 346 | struct rxrpc_connection *conn, *candidate = NULL; |
@@ -354,9 +358,9 @@ struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_transport *trans | |||
354 | cid = sp->hdr.cid & RXRPC_CIDMASK; | 358 | cid = sp->hdr.cid & RXRPC_CIDMASK; |
355 | 359 | ||
356 | /* search the connection list first */ | 360 | /* search the connection list first */ |
357 | read_lock_bh(&trans->conn_lock); | 361 | read_lock_bh(&peer->conn_lock); |
358 | 362 | ||
359 | p = trans->server_conns.rb_node; | 363 | p = peer->service_conns.rb_node; |
360 | while (p) { | 364 | while (p) { |
361 | conn = rb_entry(p, struct rxrpc_connection, service_node); | 365 | conn = rb_entry(p, struct rxrpc_connection, service_node); |
362 | 366 | ||
@@ -373,7 +377,7 @@ struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_transport *trans | |||
373 | else | 377 | else |
374 | goto found_extant_connection; | 378 | goto found_extant_connection; |
375 | } | 379 | } |
376 | read_unlock_bh(&trans->conn_lock); | 380 | read_unlock_bh(&peer->conn_lock); |
377 | 381 | ||
378 | /* not yet present - create a candidate for a new record and then | 382 | /* not yet present - create a candidate for a new record and then |
379 | * redo the search */ | 383 | * redo the search */ |
@@ -383,13 +387,12 @@ struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_transport *trans | |||
383 | return ERR_PTR(-ENOMEM); | 387 | return ERR_PTR(-ENOMEM); |
384 | } | 388 | } |
385 | 389 | ||
386 | candidate->trans = trans; | 390 | candidate->proto.local = local; |
387 | candidate->proto.local = trans->local; | ||
388 | candidate->proto.epoch = sp->hdr.epoch; | 391 | candidate->proto.epoch = sp->hdr.epoch; |
389 | candidate->proto.cid = sp->hdr.cid & RXRPC_CIDMASK; | 392 | candidate->proto.cid = sp->hdr.cid & RXRPC_CIDMASK; |
390 | candidate->proto.in_clientflag = RXRPC_CLIENT_INITIATED; | 393 | candidate->proto.in_clientflag = RXRPC_CLIENT_INITIATED; |
391 | candidate->params.local = trans->local; | 394 | candidate->params.local = local; |
392 | candidate->params.peer = trans->peer; | 395 | candidate->params.peer = peer; |
393 | candidate->params.service_id = sp->hdr.serviceId; | 396 | candidate->params.service_id = sp->hdr.serviceId; |
394 | candidate->security_ix = sp->hdr.securityIndex; | 397 | candidate->security_ix = sp->hdr.securityIndex; |
395 | candidate->out_clientflag = 0; | 398 | candidate->out_clientflag = 0; |
@@ -397,9 +400,9 @@ struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_transport *trans | |||
397 | if (candidate->params.service_id) | 400 | if (candidate->params.service_id) |
398 | candidate->state = RXRPC_CONN_SERVER_UNSECURED; | 401 | candidate->state = RXRPC_CONN_SERVER_UNSECURED; |
399 | 402 | ||
400 | write_lock_bh(&trans->conn_lock); | 403 | write_lock_bh(&peer->conn_lock); |
401 | 404 | ||
402 | pp = &trans->server_conns.rb_node; | 405 | pp = &peer->service_conns.rb_node; |
403 | p = NULL; | 406 | p = NULL; |
404 | while (*pp) { | 407 | while (*pp) { |
405 | p = *pp; | 408 | p = *pp; |
@@ -421,10 +424,11 @@ struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_transport *trans | |||
421 | conn = candidate; | 424 | conn = candidate; |
422 | candidate = NULL; | 425 | candidate = NULL; |
423 | rb_link_node(&conn->service_node, p, pp); | 426 | rb_link_node(&conn->service_node, p, pp); |
424 | rb_insert_color(&conn->service_node, &trans->server_conns); | 427 | rb_insert_color(&conn->service_node, &peer->service_conns); |
425 | atomic_inc(&conn->trans->usage); | 428 | rxrpc_get_peer(peer); |
429 | rxrpc_get_local(local); | ||
426 | 430 | ||
427 | write_unlock_bh(&trans->conn_lock); | 431 | write_unlock_bh(&peer->conn_lock); |
428 | 432 | ||
429 | write_lock(&rxrpc_connection_lock); | 433 | write_lock(&rxrpc_connection_lock); |
430 | list_add_tail(&conn->link, &rxrpc_connections); | 434 | list_add_tail(&conn->link, &rxrpc_connections); |
@@ -441,21 +445,21 @@ success: | |||
441 | /* we found the connection in the list immediately */ | 445 | /* we found the connection in the list immediately */ |
442 | found_extant_connection: | 446 | found_extant_connection: |
443 | if (sp->hdr.securityIndex != conn->security_ix) { | 447 | if (sp->hdr.securityIndex != conn->security_ix) { |
444 | read_unlock_bh(&trans->conn_lock); | 448 | read_unlock_bh(&peer->conn_lock); |
445 | goto security_mismatch; | 449 | goto security_mismatch; |
446 | } | 450 | } |
447 | rxrpc_get_connection(conn); | 451 | rxrpc_get_connection(conn); |
448 | read_unlock_bh(&trans->conn_lock); | 452 | read_unlock_bh(&peer->conn_lock); |
449 | goto success; | 453 | goto success; |
450 | 454 | ||
451 | /* we found the connection on the second time through the list */ | 455 | /* we found the connection on the second time through the list */ |
452 | found_extant_second: | 456 | found_extant_second: |
453 | if (sp->hdr.securityIndex != conn->security_ix) { | 457 | if (sp->hdr.securityIndex != conn->security_ix) { |
454 | write_unlock_bh(&trans->conn_lock); | 458 | write_unlock_bh(&peer->conn_lock); |
455 | goto security_mismatch; | 459 | goto security_mismatch; |
456 | } | 460 | } |
457 | rxrpc_get_connection(conn); | 461 | rxrpc_get_connection(conn); |
458 | write_unlock_bh(&trans->conn_lock); | 462 | write_unlock_bh(&peer->conn_lock); |
459 | kfree(candidate); | 463 | kfree(candidate); |
460 | goto success; | 464 | goto success; |
461 | 465 | ||
@@ -469,7 +473,8 @@ security_mismatch: | |||
469 | * find a connection based on transport and RxRPC connection ID for an incoming | 473 | * find a connection based on transport and RxRPC connection ID for an incoming |
470 | * packet | 474 | * packet |
471 | */ | 475 | */ |
472 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_transport *trans, | 476 | struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_local *local, |
477 | struct rxrpc_peer *peer, | ||
473 | struct sk_buff *skb) | 478 | struct sk_buff *skb) |
474 | { | 479 | { |
475 | struct rxrpc_connection *conn; | 480 | struct rxrpc_connection *conn; |
@@ -479,13 +484,13 @@ struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_transport *trans, | |||
479 | 484 | ||
480 | _enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags); | 485 | _enter(",{%x,%x}", sp->hdr.cid, sp->hdr.flags); |
481 | 486 | ||
482 | read_lock_bh(&trans->conn_lock); | 487 | read_lock_bh(&peer->conn_lock); |
483 | 488 | ||
484 | cid = sp->hdr.cid & RXRPC_CIDMASK; | 489 | cid = sp->hdr.cid & RXRPC_CIDMASK; |
485 | epoch = sp->hdr.epoch; | 490 | epoch = sp->hdr.epoch; |
486 | 491 | ||
487 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) { | 492 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) { |
488 | p = trans->server_conns.rb_node; | 493 | p = peer->service_conns.rb_node; |
489 | while (p) { | 494 | while (p) { |
490 | conn = rb_entry(p, struct rxrpc_connection, service_node); | 495 | conn = rb_entry(p, struct rxrpc_connection, service_node); |
491 | 496 | ||
@@ -508,13 +513,13 @@ struct rxrpc_connection *rxrpc_find_connection(struct rxrpc_transport *trans, | |||
508 | goto found; | 513 | goto found; |
509 | } | 514 | } |
510 | 515 | ||
511 | read_unlock_bh(&trans->conn_lock); | 516 | read_unlock_bh(&peer->conn_lock); |
512 | _leave(" = NULL"); | 517 | _leave(" = NULL"); |
513 | return NULL; | 518 | return NULL; |
514 | 519 | ||
515 | found: | 520 | found: |
516 | rxrpc_get_connection(conn); | 521 | rxrpc_get_connection(conn); |
517 | read_unlock_bh(&trans->conn_lock); | 522 | read_unlock_bh(&peer->conn_lock); |
518 | _leave(" = %p", conn); | 523 | _leave(" = %p", conn); |
519 | return conn; | 524 | return conn; |
520 | } | 525 | } |
@@ -576,8 +581,9 @@ static void rxrpc_destroy_connection(struct rxrpc_connection *conn) | |||
576 | conn->security->clear(conn); | 581 | conn->security->clear(conn); |
577 | key_put(conn->params.key); | 582 | key_put(conn->params.key); |
578 | key_put(conn->server_key); | 583 | key_put(conn->server_key); |
584 | rxrpc_put_peer(conn->params.peer); | ||
585 | rxrpc_put_local(conn->params.local); | ||
579 | 586 | ||
580 | rxrpc_put_transport(conn->trans); | ||
581 | kfree(conn); | 587 | kfree(conn); |
582 | _leave(""); | 588 | _leave(""); |
583 | } | 589 | } |
@@ -588,6 +594,7 @@ static void rxrpc_destroy_connection(struct rxrpc_connection *conn) | |||
588 | static void rxrpc_connection_reaper(struct work_struct *work) | 594 | static void rxrpc_connection_reaper(struct work_struct *work) |
589 | { | 595 | { |
590 | struct rxrpc_connection *conn, *_p; | 596 | struct rxrpc_connection *conn, *_p; |
597 | struct rxrpc_peer *peer; | ||
591 | unsigned long now, earliest, reap_time; | 598 | unsigned long now, earliest, reap_time; |
592 | 599 | ||
593 | LIST_HEAD(graveyard); | 600 | LIST_HEAD(graveyard); |
@@ -624,7 +631,8 @@ static void rxrpc_connection_reaper(struct work_struct *work) | |||
624 | 631 | ||
625 | spin_unlock(&local->client_conns_lock); | 632 | spin_unlock(&local->client_conns_lock); |
626 | } else { | 633 | } else { |
627 | write_lock_bh(&conn->trans->conn_lock); | 634 | peer = conn->params.peer; |
635 | write_lock_bh(&peer->conn_lock); | ||
628 | reap_time = conn->put_time + rxrpc_connection_expiry; | 636 | reap_time = conn->put_time + rxrpc_connection_expiry; |
629 | 637 | ||
630 | if (atomic_read(&conn->usage) > 0) { | 638 | if (atomic_read(&conn->usage) > 0) { |
@@ -632,12 +640,12 @@ static void rxrpc_connection_reaper(struct work_struct *work) | |||
632 | } else if (reap_time <= now) { | 640 | } else if (reap_time <= now) { |
633 | list_move_tail(&conn->link, &graveyard); | 641 | list_move_tail(&conn->link, &graveyard); |
634 | rb_erase(&conn->service_node, | 642 | rb_erase(&conn->service_node, |
635 | &conn->trans->server_conns); | 643 | &peer->service_conns); |
636 | } else if (reap_time < earliest) { | 644 | } else if (reap_time < earliest) { |
637 | earliest = reap_time; | 645 | earliest = reap_time; |
638 | } | 646 | } |
639 | 647 | ||
640 | write_unlock_bh(&conn->trans->conn_lock); | 648 | write_unlock_bh(&peer->conn_lock); |
641 | } | 649 | } |
642 | } | 650 | } |
643 | write_unlock(&rxrpc_connection_lock); | 651 | write_unlock(&rxrpc_connection_lock); |
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index 799aec18aa7b..f4bd57b77b93 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c | |||
@@ -631,7 +631,6 @@ static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local, | |||
631 | struct sk_buff *skb) | 631 | struct sk_buff *skb) |
632 | { | 632 | { |
633 | struct rxrpc_peer *peer; | 633 | struct rxrpc_peer *peer; |
634 | struct rxrpc_transport *trans; | ||
635 | struct rxrpc_connection *conn; | 634 | struct rxrpc_connection *conn; |
636 | struct sockaddr_rxrpc srx; | 635 | struct sockaddr_rxrpc srx; |
637 | 636 | ||
@@ -641,13 +640,8 @@ static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local, | |||
641 | if (!peer) | 640 | if (!peer) |
642 | goto cant_find_peer; | 641 | goto cant_find_peer; |
643 | 642 | ||
644 | trans = rxrpc_find_transport(local, peer); | 643 | conn = rxrpc_find_connection(local, peer, skb); |
645 | rcu_read_unlock(); | 644 | rcu_read_unlock(); |
646 | if (!trans) | ||
647 | goto cant_find_conn; | ||
648 | |||
649 | conn = rxrpc_find_connection(trans, skb); | ||
650 | rxrpc_put_transport(trans); | ||
651 | if (!conn) | 645 | if (!conn) |
652 | goto cant_find_conn; | 646 | goto cant_find_conn; |
653 | 647 | ||
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 8e24939aeac8..f4bda06b7d2d 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c | |||
@@ -140,10 +140,8 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, | |||
140 | unsigned long user_call_ID, bool exclusive) | 140 | unsigned long user_call_ID, bool exclusive) |
141 | { | 141 | { |
142 | struct rxrpc_conn_parameters cp; | 142 | struct rxrpc_conn_parameters cp; |
143 | struct rxrpc_transport *trans; | ||
144 | struct rxrpc_call *call; | 143 | struct rxrpc_call *call; |
145 | struct key *key; | 144 | struct key *key; |
146 | long ret; | ||
147 | 145 | ||
148 | DECLARE_SOCKADDR(struct sockaddr_rxrpc *, srx, msg->msg_name); | 146 | DECLARE_SOCKADDR(struct sockaddr_rxrpc *, srx, msg->msg_name); |
149 | 147 | ||
@@ -162,30 +160,10 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, | |||
162 | cp.security_level = rx->min_sec_level; | 160 | cp.security_level = rx->min_sec_level; |
163 | cp.exclusive = rx->exclusive | exclusive; | 161 | cp.exclusive = rx->exclusive | exclusive; |
164 | cp.service_id = srx->srx_service; | 162 | cp.service_id = srx->srx_service; |
165 | trans = rxrpc_name_to_transport(&cp, msg->msg_name, msg->msg_namelen, | 163 | call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, GFP_KERNEL); |
166 | GFP_KERNEL); | ||
167 | if (IS_ERR(trans)) { | ||
168 | ret = PTR_ERR(trans); | ||
169 | goto out; | ||
170 | } | ||
171 | cp.peer = trans->peer; | ||
172 | |||
173 | call = rxrpc_new_client_call(rx, &cp, trans, srx, user_call_ID, | ||
174 | GFP_KERNEL); | ||
175 | rxrpc_put_transport(trans); | ||
176 | if (IS_ERR(call)) { | ||
177 | ret = PTR_ERR(call); | ||
178 | goto out_trans; | ||
179 | } | ||
180 | 164 | ||
181 | _leave(" = %p\n", call); | 165 | _leave(" = %p\n", call); |
182 | return call; | 166 | return call; |
183 | |||
184 | out_trans: | ||
185 | rxrpc_put_transport(trans); | ||
186 | out: | ||
187 | _leave(" = %ld", ret); | ||
188 | return ERR_PTR(ret); | ||
189 | } | 167 | } |
190 | 168 | ||
191 | /* | 169 | /* |
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c index 6baad708f3b1..01d4930a11f7 100644 --- a/net/rxrpc/peer_object.c +++ b/net/rxrpc/peer_object.c | |||
@@ -188,6 +188,8 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp) | |||
188 | INIT_HLIST_HEAD(&peer->error_targets); | 188 | INIT_HLIST_HEAD(&peer->error_targets); |
189 | INIT_WORK(&peer->error_distributor, | 189 | INIT_WORK(&peer->error_distributor, |
190 | &rxrpc_peer_error_distributor); | 190 | &rxrpc_peer_error_distributor); |
191 | peer->service_conns = RB_ROOT; | ||
192 | rwlock_init(&peer->conn_lock); | ||
191 | spin_lock_init(&peer->lock); | 193 | spin_lock_init(&peer->lock); |
192 | peer->debug_id = atomic_inc_return(&rxrpc_debug_id); | 194 | peer->debug_id = atomic_inc_return(&rxrpc_debug_id); |
193 | } | 195 | } |
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c index a99690a8a3da..03ad08774d4e 100644 --- a/net/rxrpc/sysctl.c +++ b/net/rxrpc/sysctl.c | |||
@@ -90,14 +90,6 @@ static struct ctl_table rxrpc_sysctl_table[] = { | |||
90 | .proc_handler = proc_dointvec_minmax, | 90 | .proc_handler = proc_dointvec_minmax, |
91 | .extra1 = (void *)&one, | 91 | .extra1 = (void *)&one, |
92 | }, | 92 | }, |
93 | { | ||
94 | .procname = "transport_expiry", | ||
95 | .data = &rxrpc_transport_expiry, | ||
96 | .maxlen = sizeof(unsigned int), | ||
97 | .mode = 0644, | ||
98 | .proc_handler = proc_dointvec_minmax, | ||
99 | .extra1 = (void *)&one, | ||
100 | }, | ||
101 | 93 | ||
102 | /* Non-time values */ | 94 | /* Non-time values */ |
103 | { | 95 | { |
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c deleted file mode 100644 index 71947402d071..000000000000 --- a/net/rxrpc/transport.c +++ /dev/null | |||
@@ -1,265 +0,0 @@ | |||
1 | /* RxRPC point-to-point transport session management | ||
2 | * | ||
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/net.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <net/sock.h> | ||
19 | #include <net/af_rxrpc.h> | ||
20 | #include "ar-internal.h" | ||
21 | |||
22 | /* | ||
23 | * Time after last use at which transport record is cleaned up. | ||
24 | */ | ||
25 | unsigned int rxrpc_transport_expiry = 3600 * 24; | ||
26 | |||
27 | static void rxrpc_transport_reaper(struct work_struct *work); | ||
28 | |||
29 | static LIST_HEAD(rxrpc_transports); | ||
30 | static DEFINE_RWLOCK(rxrpc_transport_lock); | ||
31 | static DECLARE_DELAYED_WORK(rxrpc_transport_reap, rxrpc_transport_reaper); | ||
32 | |||
33 | /* | ||
34 | * allocate a new transport session manager | ||
35 | */ | ||
36 | static struct rxrpc_transport *rxrpc_alloc_transport(struct rxrpc_local *local, | ||
37 | struct rxrpc_peer *peer, | ||
38 | gfp_t gfp) | ||
39 | { | ||
40 | struct rxrpc_transport *trans; | ||
41 | |||
42 | _enter(""); | ||
43 | |||
44 | trans = kzalloc(sizeof(struct rxrpc_transport), gfp); | ||
45 | if (trans) { | ||
46 | trans->local = local; | ||
47 | trans->peer = peer; | ||
48 | INIT_LIST_HEAD(&trans->link); | ||
49 | trans->server_conns = RB_ROOT; | ||
50 | rwlock_init(&trans->conn_lock); | ||
51 | atomic_set(&trans->usage, 1); | ||
52 | trans->debug_id = atomic_inc_return(&rxrpc_debug_id); | ||
53 | } | ||
54 | |||
55 | _leave(" = %p", trans); | ||
56 | return trans; | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * obtain a transport session for the nominated endpoints | ||
61 | */ | ||
62 | struct rxrpc_transport *rxrpc_get_transport(struct rxrpc_local *local, | ||
63 | struct rxrpc_peer *peer, | ||
64 | gfp_t gfp) | ||
65 | { | ||
66 | struct rxrpc_transport *trans, *candidate; | ||
67 | const char *new = "old"; | ||
68 | int usage; | ||
69 | |||
70 | _enter("{%pI4+%hu},{%pI4+%hu},", | ||
71 | &local->srx.transport.sin.sin_addr, | ||
72 | ntohs(local->srx.transport.sin.sin_port), | ||
73 | &peer->srx.transport.sin.sin_addr, | ||
74 | ntohs(peer->srx.transport.sin.sin_port)); | ||
75 | |||
76 | /* search the transport list first */ | ||
77 | read_lock_bh(&rxrpc_transport_lock); | ||
78 | list_for_each_entry(trans, &rxrpc_transports, link) { | ||
79 | if (trans->local == local && trans->peer == peer) | ||
80 | goto found_extant_transport; | ||
81 | } | ||
82 | read_unlock_bh(&rxrpc_transport_lock); | ||
83 | |||
84 | /* not yet present - create a candidate for a new record and then | ||
85 | * redo the search */ | ||
86 | candidate = rxrpc_alloc_transport(local, peer, gfp); | ||
87 | if (!candidate) { | ||
88 | _leave(" = -ENOMEM"); | ||
89 | return ERR_PTR(-ENOMEM); | ||
90 | } | ||
91 | |||
92 | write_lock_bh(&rxrpc_transport_lock); | ||
93 | |||
94 | list_for_each_entry(trans, &rxrpc_transports, link) { | ||
95 | if (trans->local == local && trans->peer == peer) | ||
96 | goto found_extant_second; | ||
97 | } | ||
98 | |||
99 | /* we can now add the new candidate to the list */ | ||
100 | trans = candidate; | ||
101 | candidate = NULL; | ||
102 | usage = atomic_read(&trans->usage); | ||
103 | |||
104 | rxrpc_get_local(trans->local); | ||
105 | rxrpc_get_peer(trans->peer); | ||
106 | list_add_tail(&trans->link, &rxrpc_transports); | ||
107 | write_unlock_bh(&rxrpc_transport_lock); | ||
108 | new = "new"; | ||
109 | |||
110 | success: | ||
111 | _net("TRANSPORT %s %d local %d -> peer %d", | ||
112 | new, | ||
113 | trans->debug_id, | ||
114 | trans->local->debug_id, | ||
115 | trans->peer->debug_id); | ||
116 | |||
117 | _leave(" = %p {u=%d}", trans, usage); | ||
118 | return trans; | ||
119 | |||
120 | /* we found the transport in the list immediately */ | ||
121 | found_extant_transport: | ||
122 | usage = atomic_inc_return(&trans->usage); | ||
123 | read_unlock_bh(&rxrpc_transport_lock); | ||
124 | goto success; | ||
125 | |||
126 | /* we found the transport on the second time through the list */ | ||
127 | found_extant_second: | ||
128 | usage = atomic_inc_return(&trans->usage); | ||
129 | write_unlock_bh(&rxrpc_transport_lock); | ||
130 | kfree(candidate); | ||
131 | goto success; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * find the transport connecting two endpoints | ||
136 | */ | ||
137 | struct rxrpc_transport *rxrpc_find_transport(struct rxrpc_local *local, | ||
138 | struct rxrpc_peer *peer) | ||
139 | { | ||
140 | struct rxrpc_transport *trans; | ||
141 | |||
142 | _enter("{%pI4+%hu},{%pI4+%hu},", | ||
143 | &local->srx.transport.sin.sin_addr, | ||
144 | ntohs(local->srx.transport.sin.sin_port), | ||
145 | &peer->srx.transport.sin.sin_addr, | ||
146 | ntohs(peer->srx.transport.sin.sin_port)); | ||
147 | |||
148 | /* search the transport list */ | ||
149 | read_lock_bh(&rxrpc_transport_lock); | ||
150 | |||
151 | list_for_each_entry(trans, &rxrpc_transports, link) { | ||
152 | if (trans->local == local && trans->peer == peer) | ||
153 | goto found_extant_transport; | ||
154 | } | ||
155 | |||
156 | read_unlock_bh(&rxrpc_transport_lock); | ||
157 | _leave(" = NULL"); | ||
158 | return NULL; | ||
159 | |||
160 | found_extant_transport: | ||
161 | atomic_inc(&trans->usage); | ||
162 | read_unlock_bh(&rxrpc_transport_lock); | ||
163 | _leave(" = %p", trans); | ||
164 | return trans; | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * release a transport session | ||
169 | */ | ||
170 | void rxrpc_put_transport(struct rxrpc_transport *trans) | ||
171 | { | ||
172 | _enter("%p{u=%d}", trans, atomic_read(&trans->usage)); | ||
173 | |||
174 | ASSERTCMP(atomic_read(&trans->usage), >, 0); | ||
175 | |||
176 | trans->put_time = ktime_get_seconds(); | ||
177 | if (unlikely(atomic_dec_and_test(&trans->usage))) { | ||
178 | _debug("zombie"); | ||
179 | /* let the reaper determine the timeout to avoid a race with | ||
180 | * overextending the timeout if the reaper is running at the | ||
181 | * same time */ | ||
182 | rxrpc_queue_delayed_work(&rxrpc_transport_reap, 0); | ||
183 | } | ||
184 | _leave(""); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * clean up a transport session | ||
189 | */ | ||
190 | static void rxrpc_cleanup_transport(struct rxrpc_transport *trans) | ||
191 | { | ||
192 | _net("DESTROY TRANS %d", trans->debug_id); | ||
193 | |||
194 | rxrpc_put_local(trans->local); | ||
195 | rxrpc_put_peer(trans->peer); | ||
196 | kfree(trans); | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * reap dead transports that have passed their expiry date | ||
201 | */ | ||
202 | static void rxrpc_transport_reaper(struct work_struct *work) | ||
203 | { | ||
204 | struct rxrpc_transport *trans, *_p; | ||
205 | unsigned long now, earliest, reap_time; | ||
206 | |||
207 | LIST_HEAD(graveyard); | ||
208 | |||
209 | _enter(""); | ||
210 | |||
211 | now = ktime_get_seconds(); | ||
212 | earliest = ULONG_MAX; | ||
213 | |||
214 | /* extract all the transports that have been dead too long */ | ||
215 | write_lock_bh(&rxrpc_transport_lock); | ||
216 | list_for_each_entry_safe(trans, _p, &rxrpc_transports, link) { | ||
217 | _debug("reap TRANS %d { u=%d t=%ld }", | ||
218 | trans->debug_id, atomic_read(&trans->usage), | ||
219 | (long) now - (long) trans->put_time); | ||
220 | |||
221 | if (likely(atomic_read(&trans->usage) > 0)) | ||
222 | continue; | ||
223 | |||
224 | reap_time = trans->put_time + rxrpc_transport_expiry; | ||
225 | if (reap_time <= now) | ||
226 | list_move_tail(&trans->link, &graveyard); | ||
227 | else if (reap_time < earliest) | ||
228 | earliest = reap_time; | ||
229 | } | ||
230 | write_unlock_bh(&rxrpc_transport_lock); | ||
231 | |||
232 | if (earliest != ULONG_MAX) { | ||
233 | _debug("reschedule reaper %ld", (long) earliest - now); | ||
234 | ASSERTCMP(earliest, >, now); | ||
235 | rxrpc_queue_delayed_work(&rxrpc_transport_reap, | ||
236 | (earliest - now) * HZ); | ||
237 | } | ||
238 | |||
239 | /* then destroy all those pulled out */ | ||
240 | while (!list_empty(&graveyard)) { | ||
241 | trans = list_entry(graveyard.next, struct rxrpc_transport, | ||
242 | link); | ||
243 | list_del_init(&trans->link); | ||
244 | |||
245 | ASSERTCMP(atomic_read(&trans->usage), ==, 0); | ||
246 | rxrpc_cleanup_transport(trans); | ||
247 | } | ||
248 | |||
249 | _leave(""); | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * preemptively destroy all the transport session records rather than waiting | ||
254 | * for them to time out | ||
255 | */ | ||
256 | void __exit rxrpc_destroy_all_transports(void) | ||
257 | { | ||
258 | _enter(""); | ||
259 | |||
260 | rxrpc_transport_expiry = 0; | ||
261 | cancel_delayed_work(&rxrpc_transport_reap); | ||
262 | rxrpc_queue_delayed_work(&rxrpc_transport_reap, 0); | ||
263 | |||
264 | _leave(""); | ||
265 | } | ||