• Vlad Buslov's avatar
    net: sched: protect block state with mutex · c266f64d
    Vlad Buslov authored
    Currently, tcf_block doesn't use any synchronization mechanisms to protect
    critical sections that manage lifetime of its chains. block->chain_list and
    multiple variables in tcf_chain that control its lifetime assume external
    synchronization provided by global rtnl lock. Converting chain reference
    counting to atomic reference counters is not possible because cls API uses
    multiple counters and flags to control chain lifetime, so all of them must
    be synchronized in chain get/put code.
    
    Use single per-block lock to protect block data and manage lifetime of all
    chains on the block. Always take block->lock when accessing chain_list.
    Chain get and put modify chain lifetime-management data and parent block's
    chain_list, so take the lock in these functions. Verify block->lock state
    with assertions in functions that expect to be called with the lock taken
    and are called from multiple places. Take block->lock when accessing
    filter_chain_list.
    
    In order to allow parallel update of rules on single block, move all calls
    to classifiers outside of critical sections protected by new block->lock.
    Rearrange chain get and put functions code to only access protected chain
    data while holding block lock:
    - Rearrange code to only access chain reference counter and chain action
      reference counter while holding block lock.
    - Extract code that requires block->lock from tcf_chain_destroy() into
      standalone tcf_chain_destroy() function that is called by
      __tcf_chain_put() in same critical section that changes chain reference
      counters.
    Signed-off-by: default avatarVlad Buslov <vladbu@mellanox.com>
    Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    c266f64d
cls_api.c 67.1 KB