• Ioannis Angelakopoulos's avatar
    btrfs: add macros for annotating wait events with lockdep · ab9a323f
    Ioannis Angelakopoulos authored
    Introduce four macros that are used to annotate wait events in btrfs code
    with lockdep;
    
      1) the btrfs_lockdep_init_map
      2) the btrfs_lockdep_acquire,
      3) the btrfs_lockdep_release
      4) the btrfs_might_wait_for_event macros.
    
    The btrfs_lockdep_init_map macro is used to initialize a lockdep map.
    
    The btrfs_lockdep_<acquire,release> macros are used by threads to take
    the lockdep map as readers (shared lock) and release it, respectively.
    
    The btrfs_might_wait_for_event macro is used by threads to take the
    lockdep map as writers (exclusive lock) and release it.
    
    In general, the lockdep annotation for wait events work as follows:
    
    The condition for a wait event can be modified and signaled at the same
    time by multiple threads. These threads hold the lockdep map as readers
    when they enter a context in which blocking would prevent signaling the
    condition. Frequently, this occurs when a thread violates a condition
    (lockdep map acquire), before restoring it and signaling it at a later
    point (lockdep map release).
    
    The threads that block on the wait event take the lockdep map as writers
    (exclusive lock). These threads have to block until all the threads that
    hold the lockdep map as readers signal the condition for the wait event
    and release the lockdep map.
    
    The lockdep annotation is used to warn about potential deadlock scenarios
    that involve the threads that modify and signal the wait event condition
    and threads that block on the wait event. A simple example is illustrated
    below:
    
    Without lockdep:
    
    TA                                        TB
    cond = false
                                              lock(A)
                                              wait_event(w, cond)
                                              unlock(A)
    lock(A)
    cond = true
    signal(w)
    unlock(A)
    
    With lockdep:
    
    TA                                        TB
    rwsem_acquire_read(lockdep_map)
    cond = false
                                              lock(A)
                                              rwsem_acquire(lockdep_map)
                                              rwsem_release(lockdep_map)
                                              wait_event(w, cond)
                                              unlock(A)
    lock(A)
    cond = true
    signal(w)
    unlock(A)
    rwsem_release(lockdep_map)
    
    In the second case, with the lockdep annotation, lockdep would warn about
    an ABBA deadlock, while the first case would just deadlock at some point.
    Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Signed-off-by: default avatarIoannis Angelakopoulos <iangelak@fb.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    ab9a323f
ctree.h 139 KB