Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rxrpc: Move peer lookup from call-accept to new-incoming-conn

Move the lookup of a peer from a call that's being accepted into the
function that creates a new incoming connection. This will allow us to
avoid incrementing the peer's usage count in some cases in future.

Note that I haven't bother to integrate rxrpc_get_addr_from_skb() with
rxrpc_extract_addr_from_skb() as I'm going to delete the former in the very
near future.

Signed-off-by: David Howells <dhowells@redhat.com>

+51 -26
+2 -1
net/rxrpc/ar-internal.h
··· 607 607 * conn_service.c 608 608 */ 609 609 struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *, 610 - struct rxrpc_peer *, 610 + struct sockaddr_rxrpc *, 611 611 struct sk_buff *); 612 612 613 613 /* ··· 773 773 */ 774 774 void rxrpc_get_addr_from_skb(struct rxrpc_local *, const struct sk_buff *, 775 775 struct sockaddr_rxrpc *); 776 + int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *); 776 777 777 778 /* 778 779 * debug tracing
+7 -24
net/rxrpc/call_accept.c
··· 75 75 { 76 76 struct rxrpc_connection *conn; 77 77 struct rxrpc_skb_priv *sp, *nsp; 78 - struct rxrpc_peer *peer; 79 78 struct rxrpc_call *call; 80 79 struct sk_buff *notification; 81 80 int ret; ··· 93 94 rxrpc_new_skb(notification); 94 95 notification->mark = RXRPC_SKB_MARK_NEW_CALL; 95 96 96 - peer = rxrpc_lookup_peer(local, srx, GFP_NOIO); 97 - if (!peer) { 98 - _debug("no peer"); 99 - ret = -EBUSY; 100 - goto error; 101 - } 102 - 103 - conn = rxrpc_incoming_connection(local, peer, skb); 104 - rxrpc_put_peer(peer); 97 + conn = rxrpc_incoming_connection(local, srx, skb); 105 98 if (IS_ERR(conn)) { 106 99 _debug("no conn"); 107 100 ret = PTR_ERR(conn); ··· 217 226 whdr._rsvd = 0; 218 227 whdr.serviceId = htons(sp->hdr.serviceId); 219 228 220 - /* determine the remote address */ 221 - memset(&srx, 0, sizeof(srx)); 222 - srx.srx_family = AF_RXRPC; 223 - srx.transport.family = local->srx.transport.family; 224 - srx.transport_type = local->srx.transport_type; 225 - switch (srx.transport.family) { 226 - case AF_INET: 227 - srx.transport_len = sizeof(struct sockaddr_in); 228 - srx.transport.sin.sin_port = udp_hdr(skb)->source; 229 - srx.transport.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; 230 - break; 231 - default: 232 - goto busy; 233 - } 229 + if (rxrpc_extract_addr_from_skb(&srx, skb) < 0) 230 + goto drop; 234 231 235 232 /* get the socket providing the service */ 236 233 read_lock_bh(&local->services_lock); ··· 261 282 read_unlock_bh(&local->services_lock); 262 283 busy: 263 284 rxrpc_busy(local, &srx, &whdr); 285 + rxrpc_free_skb(skb); 286 + return; 287 + 288 + drop: 264 289 rxrpc_free_skb(skb); 265 290 return; 266 291
+10 -1
net/rxrpc/conn_service.c
··· 16 16 * get a record of an incoming connection 17 17 */ 18 18 struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *local, 19 - struct rxrpc_peer *peer, 19 + struct sockaddr_rxrpc *srx, 20 20 struct sk_buff *skb) 21 21 { 22 22 struct rxrpc_connection *conn, *candidate = NULL; 23 23 struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 24 + struct rxrpc_peer *peer; 24 25 struct rb_node *p, **pp; 25 26 const char *new = "old"; 26 27 u32 epoch, cid; 27 28 28 29 _enter(""); 30 + 31 + peer = rxrpc_lookup_peer(local, srx, GFP_NOIO); 32 + if (!peer) { 33 + _debug("no peer"); 34 + return ERR_PTR(-EBUSY); 35 + } 29 36 30 37 ASSERT(sp->hdr.flags & RXRPC_CLIENT_INITIATED); 31 38 ··· 65 58 * redo the search */ 66 59 candidate = rxrpc_alloc_connection(GFP_NOIO); 67 60 if (!candidate) { 61 + rxrpc_put_peer(peer); 68 62 _leave(" = -ENOMEM"); 69 63 return ERR_PTR(-ENOMEM); 70 64 } ··· 122 114 success: 123 115 _net("CONNECTION %s %d {%x}", new, conn->debug_id, conn->proto.cid); 124 116 117 + rxrpc_put_peer(peer); 125 118 _leave(" = %p {u=%d}", conn, atomic_read(&conn->usage)); 126 119 return conn; 127 120
+32
net/rxrpc/utils.c
··· 10 10 */ 11 11 12 12 #include <linux/ip.h> 13 + #include <linux/ipv6.h> 13 14 #include <linux/udp.h> 14 15 #include "ar-internal.h" 15 16 ··· 38 37 39 38 default: 40 39 BUG(); 40 + } 41 + } 42 + 43 + /* 44 + * Fill out a peer address from a socket buffer containing a packet. 45 + */ 46 + int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *srx, struct sk_buff *skb) 47 + { 48 + memset(srx, 0, sizeof(*srx)); 49 + 50 + switch (ntohs(skb->protocol)) { 51 + case ETH_P_IP: 52 + srx->transport_type = SOCK_DGRAM; 53 + srx->transport_len = sizeof(srx->transport.sin); 54 + srx->transport.sin.sin_family = AF_INET; 55 + srx->transport.sin.sin_port = udp_hdr(skb)->source; 56 + srx->transport.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; 57 + return 0; 58 + 59 + case ETH_P_IPV6: 60 + srx->transport_type = SOCK_DGRAM; 61 + srx->transport_len = sizeof(srx->transport.sin6); 62 + srx->transport.sin6.sin6_family = AF_INET6; 63 + srx->transport.sin6.sin6_port = udp_hdr(skb)->source; 64 + srx->transport.sin6.sin6_addr = ipv6_hdr(skb)->saddr; 65 + return 0; 66 + 67 + default: 68 + pr_warn_ratelimited("AF_RXRPC: Unknown eth protocol %u\n", 69 + ntohs(skb->protocol)); 70 + return -EAFNOSUPPORT; 41 71 } 42 72 }