Files
linux/fs
Aneesh Kumar K.V b113a5a2f7 hugetlbfs: avoid taking i_mutex from hugetlbfs_read()
commit a05b0855fd upstream.

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: Aneesh 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>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-04-02 09:27:11 -07:00
..
2011-03-31 11:26:23 -03:00
2011-03-31 11:26:23 -03:00
2011-05-19 16:55:28 +09:30
2011-07-17 23:20:29 -04:00
2011-12-21 12:57:44 -08:00
2011-11-11 09:35:59 -08:00
2011-06-20 17:53:24 -05:00
2011-03-31 11:26:23 -03:00
2011-03-31 11:26:23 -03:00
2011-06-03 18:24:58 -04:00
2011-04-14 16:06:56 -07:00
2011-07-17 23:21:35 -04:00
2012-03-19 08:57:43 -07:00
2011-07-06 12:15:16 -07:00
2012-01-25 17:24:51 -08:00
2012-02-29 16:34:35 -08:00
2011-07-06 10:41:13 -07:00
2011-05-26 10:01:43 -06:00
2011-05-23 19:58:53 +02:00
2011-06-03 18:24:58 -04:00