• David Howells's avatar
    rxrpc: Implement local endpoint cache · b2347cb5
    David Howells authored
    Implement the local RxRPC endpoint cache.  Only the primary cache is used.
    This is indexed on the following details:
    
      - Local network transport family - currently only AF_INET.
      - Local network transport type - currently only UDP.
      - Local network transport address.
    
    The hash isn't very big since we don't expect to have many local endpoints
    hanging around - RxRPC sockets opened with a 0 service ID (ie. client-only
    sockets) share local endpoints if they have matching local network
    addresses (typically all zeros).
    
    We use a mutex to handle lookups and don't provide RCU-only lookups since
    we only expect write access to this cache to be done from process context
    when opening a socket.  The local endpoint object is pointed to by the
    transport socket's sk_user_data for the life of the transport socket so
    that it's fast to access by the transport socket sk_data_ready and
    sk_error_report callbacks.
    
    Further, the transport socket is shut down before we clear the sk_user_data
    pointer, so that we can be sure that the transport socket's callbacks won't
    be invoked once the RCU destruction is scheduled.
    
    The local endpoint retains the transport socket that we use to send and
    capture packets and capture network error messages (ICMP).  The socket is
    opened when an endpoint is looked up - if it doesn't already exist.
    
    Note that to make this work, we have to get rid of rxrpc_local_lock as that
    causes a potential deadlock between a softirq looking in an object cache
    whilst holding that lock vs objcache_clear() taking the cache lock and then
    an interrupt.
    
    However, since the socket is locked by the caller of the rxrpc_data_ready()
    function and given that we don't clear sk_user_data until after we've shut
    down the socket, we are guaranteed that the local endpoint struct is pinned
    until rxrpc_data_ready() returns - so we don't need to lock the local
    endpoint struct there.
    
    The other places we've taken the lock where we read the usage count and
    then increment it if not zero can be replaced by atomic_inc_not_zero()
    (hidden inside rxrpc_get_local_maybe()).
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    b2347cb5
ar-internal.h 30.4 KB