• Aneesh Kumar K.V's avatar
    hugetlbfs: avoid taking i_mutex from hugetlbfs_read() · a05b0855
    Aneesh Kumar K.V authored
    Taking i_mutex in hugetlbfs_read() can result in deadlock with mmap as
    explained below
    
     Thread A:
      read() on hugetlbfs
       hugetlbfs_read() called
        i_mutex grabbed
         hugetlbfs_read_actor() called
          __copy_to_user() called
           page fault is triggered
     Thread B, sharing address space with A:
      mmap() the same file
       ->mmap_sem is grabbed on task_B->mm->mmap_sem
        hugetlbfs_file_mmap() is called
         attempt to grab ->i_mutex and block waiting for A to give it up
     Thread A:
      pagefault handled blocked on attempt to grab task_A->mm->mmap_sem,
     which happens to be the same thing as task_B->mm->mmap_sem.  Block waiting
     for B to give it up.
    
    AFAIU the i_mutex locking was added to hugetlbfs_read() as per
    http://lkml.indiana.edu/hypermail/linux/kernel/0707.2/3066.html to take
    care of the race between truncate and read.  This patch fixes this by
    looking at page->mapping under lock_page() (find_lock_page()) to ensure
    that the inode didn't get truncated in the range during a parallel read.
    
    Ideally we can extend the patch to make sure we don't increase i_size in
    mmap.  But that will break userspace, because applications will now have
    to use truncate(2) to increase i_size in hugetlbfs.
    
    Based on the original patch from Hillf Danton.
    Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
    Cc: Hillf Danton <dhillf@gmail.com>
    Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
    Cc: Al Viro <viro@zeniv.linux.org.uk>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: <stable@kernel.org>		[everything after 2007 :)]
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    a05b0855
inode.c 24.5 KB