Skip to content
  • Eric Dumazet's avatar
    net: sock_def_readable() and friends RCU conversion · 43815482
    Eric Dumazet authored
    
    
    sk_callback_lock rwlock actually protects sk->sk_sleep pointer, so we
    need two atomic operations (and associated dirtying) per incoming
    packet.
    
    RCU conversion is pretty much needed :
    
    1) Add a new structure, called "struct socket_wq" to hold all fields
    that will need rcu_read_lock() protection (currently: a
    wait_queue_head_t and a struct fasync_struct pointer).
    
    [Future patch will add a list anchor for wakeup coalescing]
    
    2) Attach one of such structure to each "struct socket" created in
    sock_alloc_inode().
    
    3) Respect RCU grace period when freeing a "struct socket_wq"
    
    4) Change sk_sleep pointer in "struct sock" by sk_wq, pointer to "struct
    socket_wq"
    
    5) Change sk_sleep() function to use new sk->sk_wq instead of
    sk->sk_sleep
    
    6) Change sk_has_sleeper() to wq_has_sleeper() that must be used inside
    a rcu_read_lock() section.
    
    7) Change all sk_has_sleeper() callers to :
      - Use rcu_read_lock() instead of read_lock(&sk->sk_callback_lock)
      - Use wq_has_sleeper() to eventually wakeup tasks.
      - Use rcu_read_unlock() instead of read_unlock(&sk->sk_callback_lock)
    
    8) sock_wake_async() is modified to use rcu protection as well.
    
    9) Exceptions :
      macvtap, drivers/net/tun.c, af_unix use integrated "struct socket_wq"
    instead of dynamically allocated ones. They dont need rcu freeing.
    
    Some cleanups or followups are probably needed, (possible
    sk_callback_lock conversion to a spinlock for example...).
    
    Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    43815482