aboutsummaryrefslogtreecommitdiffstats
path: root/net/rxrpc/input.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-04-04 14:00:32 +0100
committerDavid Howells <dhowells@redhat.com>2016-06-15 10:12:33 +0100
commitbe6e6707f6eec2048d9be608bc0ceecde5bd4cef (patch)
treeda92ce7ff67efa365ba27ddb5742bdc3698e0836 /net/rxrpc/input.c
parentact_police: rename tcf_act_police_locate() to tcf_act_police_init() (diff)
downloadlinux-dev-be6e6707f6eec2048d9be608bc0ceecde5bd4cef.tar.xz
linux-dev-be6e6707f6eec2048d9be608bc0ceecde5bd4cef.zip
rxrpc: Rework peer object handling to use hash table and RCU
Rework peer object handling to use a hash table instead of a flat list and to use RCU. Peer objects are no longer destroyed by passing them to a workqueue to process, but rather are just passed to the RCU garbage collector as kfree'able objects. The hash function uses the local endpoint plus all the components of the remote address, except for the RxRPC service ID. Peers thus represent a UDP port on the remote machine as contacted by a UDP port on this machine. The RCU read lock is used to handle non-creating lookups so that they can be called from bottom half context in the sk_error_report handler without having to lock the hash table against modification. rxrpc_lookup_peer_rcu() *does* take a reference on the peer object as in the future, this will be passed to a work item for error distribution in the error_report path and this function will cease being used in the data_ready path. Creating lookups are done under spinlock rather than mutex as they might be set up due to an external stimulus if the local endpoint is a server. Captured network error messages (ICMP) are handled with respect to this struct and MTU size and RTT are cached here. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/input.c')
-rw-r--r--net/rxrpc/input.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index e0815a033999..3b405dbf3a05 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -635,14 +635,16 @@ static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
struct rxrpc_peer *peer;
struct rxrpc_transport *trans;
struct rxrpc_connection *conn;
+ struct sockaddr_rxrpc srx;
- peer = rxrpc_find_peer(local, ip_hdr(skb)->saddr,
- udp_hdr(skb)->source);
+ rxrpc_get_addr_from_skb(local, skb, &srx);
+ rcu_read_lock();
+ peer = rxrpc_lookup_peer_rcu(local, &srx);
if (IS_ERR(peer))
- goto cant_find_conn;
+ goto cant_find_peer;
trans = rxrpc_find_transport(local, peer);
- rxrpc_put_peer(peer);
+ rcu_read_unlock();
if (!trans)
goto cant_find_conn;
@@ -652,6 +654,9 @@ static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
goto cant_find_conn;
return conn;
+
+cant_find_peer:
+ rcu_read_unlock();
cant_find_conn:
return NULL;
}