• Pedro Tammela's avatar
    net/sched: act_api: rely on rcu in tcf_idr_check_alloc · 4b55e867
    Pedro Tammela authored
    Instead of relying only on the idrinfo->lock mutex for
    bind/alloc logic, rely on a combination of rcu + mutex + atomics
    to better scale the case where multiple rtnl-less filters are
    binding to the same action object.
    
    Action binding happens when an action index is specified explicitly and
    an action exists which such index exists. Example:
      tc actions add action drop index 1
      tc filter add ... matchall action drop index 1
      tc filter add ... matchall action drop index 1
      tc filter add ... matchall action drop index 1
      tc filter ls ...
         filter protocol all pref 49150 matchall chain 0 filter protocol all pref 49150 matchall chain 0 handle 0x1
         not_in_hw
               action order 1: gact action drop
                random type none pass val 0
                index 1 ref 4 bind 3
    
       filter protocol all pref 49151 matchall chain 0 filter protocol all pref 49151 matchall chain 0 handle 0x1
         not_in_hw
               action order 1: gact action drop
                random type none pass val 0
                index 1 ref 4 bind 3
    
       filter protocol all pref 49152 matchall chain 0 filter protocol all pref 49152 matchall chain 0 handle 0x1
         not_in_hw
               action order 1: gact action drop
                random type none pass val 0
                index 1 ref 4 bind 3
    
    When no index is specified, as before, grab the mutex and allocate
    in the idr the next available id. In this version, as opposed to before,
    it's simplified to store the -EBUSY pointer instead of the previous
    alloc + replace combination.
    
    When an index is specified, rely on rcu to find if there's an object in
    such index. If there's none, fallback to the above, serializing on the
    mutex and reserving the specified id. If there's one, it can be an -EBUSY
    pointer, in which case we just try again until it's an action, or an action.
    Given the rcu guarantees, the action found could be dead and therefore
    we need to bump the refcount if it's not 0, handling the case it's
    in fact 0.
    
    As bind and the action refcount are already atomics, these increments can
    happen without the mutex protection while many tcf_idr_check_alloc race
    to bind to the same action instance.
    
    In case binding encounters a parallel delete or add, it will return
    -EAGAIN in order to try again. Both filter and action apis already
    have the retry machinery in-place. In case it's an unlocked filter it
    retries under the rtnl lock.
    Signed-off-by: default avatarPedro Tammela <pctammela@mojatatu.com>
    Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
    Reviewed-by: default avatarVlad Buslov <vladbu@nvidia.com>
    Link: https://lore.kernel.org/r/20231211181807.96028-2-pctammela@mojatatu.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    4b55e867
act_api.c 52.6 KB