• Waiman Long's avatar
    locking/rwsem: Prevent non-first waiter from spinning in down_write() slowpath · b613c7f3
    Waiman Long authored
    A non-first waiter can potentially spin in the for loop of
    rwsem_down_write_slowpath() without sleeping but fail to acquire the
    lock even if the rwsem is free if the following sequence happens:
    
      Non-first RT waiter    First waiter      Lock holder
      -------------------    ------------      -----------
      Acquire wait_lock
      rwsem_try_write_lock():
        Set handoff bit if RT or
          wait too long
        Set waiter->handoff_set
      Release wait_lock
                             Acquire wait_lock
                             Inherit waiter->handoff_set
                             Release wait_lock
    					   Clear owner
                                               Release lock
      if (waiter.handoff_set) {
        rwsem_spin_on_owner(();
        if (OWNER_NULL)
          goto trylock_again;
      }
      trylock_again:
      Acquire wait_lock
      rwsem_try_write_lock():
         if (first->handoff_set && (waiter != first))
    	return false;
      Release wait_lock
    
    A non-first waiter cannot really acquire the rwsem even if it mistakenly
    believes that it can spin on OWNER_NULL value. If that waiter happens
    to be an RT task running on the same CPU as the first waiter, it can
    block the first waiter from acquiring the rwsem leading to live lock.
    Fix this problem by making sure that a non-first waiter cannot spin in
    the slowpath loop without sleeping.
    
    Fixes: d257cc8c ("locking/rwsem: Make handoff bit handling more consistent")
    Signed-off-by: default avatarWaiman Long <longman@redhat.com>
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    Tested-by: default avatarMukesh Ojha <quic_mojha@quicinc.com>
    Reviewed-by: default avatarMukesh Ojha <quic_mojha@quicinc.com>
    Cc: stable@vger.kernel.org
    Link: https://lore.kernel.org/r/20230126003628.365092-2-longman@redhat.com
    b613c7f3
rwsem.c 45.5 KB