Skip to content
  • Hugh Dickins's avatar
    mm: fix invalidate_complete_page2() lock ordering · 6a91e161
    Hugh Dickins authored
    
    
    commit ec4d9f626d5908b6052c2973f37992f1db52e967 upstream.
    
    In fuzzing with trinity, lockdep protested "possible irq lock inversion
    dependency detected" when isolate_lru_page() reenabled interrupts while
    still holding the supposedly irq-safe tree_lock:
    
    invalidate_inode_pages2
      invalidate_complete_page2
        spin_lock_irq(&mapping->tree_lock)
        clear_page_mlock
          isolate_lru_page
            spin_unlock_irq(&zone->lru_lock)
    
    isolate_lru_page() is correct to enable interrupts unconditionally:
    invalidate_complete_page2() is incorrect to call clear_page_mlock() while
    holding tree_lock, which is supposed to nest inside lru_lock.
    
    Both truncate_complete_page() and invalidate_complete_page() call
    clear_page_mlock() before taking tree_lock to remove page from radix_tree.
     I guess invalidate_complete_page2() preferred to test PageDirty (again)
    under tree_lock before committing to the munlock; but since the page has
    already been unmapped, its state is already somewhat inconsistent, and no
    worse if clear_page_mlock() moved up.
    
    Reported-by: default avatarSasha Levin <levinsasha928@gmail.com>
    Deciphered-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarHugh Dickins <hughd@google.com>
    Acked-by: default avatarMel Gorman <mel@csn.ul.ie>
    Cc: Rik van Riel <riel@redhat.com>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: Michel Lespinasse <walken@google.com>
    Cc: Ying Han <yinghan@google.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    6a91e161