| From stable-bounces@linux.kernel.org Thu Dec 10 15:52:55 2009 |
| From: "Theodore Ts'o" <tytso@mit.edu> |
| Date: Thu, 10 Dec 2009 18:51:31 -0500 |
| Subject: ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem) |
| To: stable@kernel.org |
| Cc: "Theodore Ts'o" <tytso@mit.edu> |
| Message-ID: <1260489091-29892-1-git-send-email-tytso@mit.edu> |
| |
| (cherry picked from commit fab3a549e204172236779f502eccb4f9bf0dc87d) |
| |
| Fix the following potential circular locking dependency between |
| mm->mmap_sem and ei->i_data_sem: |
| |
| ======================================================= |
| [ INFO: possible circular locking dependency detected ] |
| 2.6.32-04115-gec044c5 #37 |
| ------------------------------------------------------- |
| ureadahead/1855 is trying to acquire lock: |
| (&mm->mmap_sem){++++++}, at: [<ffffffff81107224>] might_fault+0x5c/0xac |
| |
| but task is already holding lock: |
| (&ei->i_data_sem){++++..}, at: [<ffffffff811be1fd>] ext4_fiemap+0x11b/0x159 |
| |
| which lock already depends on the new lock. |
| |
| the existing dependency chain (in reverse order) is: |
| |
| -> #1 (&ei->i_data_sem){++++..}: |
| [<ffffffff81099bfa>] __lock_acquire+0xb67/0xd0f |
| [<ffffffff81099e7e>] lock_acquire+0xdc/0x102 |
| [<ffffffff81516633>] down_read+0x51/0x84 |
| [<ffffffff811a2414>] ext4_get_blocks+0x50/0x2a5 |
| [<ffffffff811a3453>] ext4_get_block+0xab/0xef |
| [<ffffffff81154f39>] do_mpage_readpage+0x198/0x48d |
| [<ffffffff81155360>] mpage_readpages+0xd0/0x114 |
| [<ffffffff811a104b>] ext4_readpages+0x1d/0x1f |
| [<ffffffff810f8644>] __do_page_cache_readahead+0x12f/0x1bc |
| [<ffffffff810f86f2>] ra_submit+0x21/0x25 |
| [<ffffffff810f0cfd>] filemap_fault+0x19f/0x32c |
| [<ffffffff81107b97>] __do_fault+0x55/0x3a2 |
| [<ffffffff81109db0>] handle_mm_fault+0x327/0x734 |
| [<ffffffff8151aaa9>] do_page_fault+0x292/0x2aa |
| [<ffffffff81518205>] page_fault+0x25/0x30 |
| [<ffffffff812a34d8>] clear_user+0x38/0x3c |
| [<ffffffff81167e16>] padzero+0x20/0x31 |
| [<ffffffff81168b47>] load_elf_binary+0x8bc/0x17ed |
| [<ffffffff81130e95>] search_binary_handler+0xc2/0x259 |
| [<ffffffff81166d64>] load_script+0x1b8/0x1cc |
| [<ffffffff81130e95>] search_binary_handler+0xc2/0x259 |
| [<ffffffff8113255f>] do_execve+0x1ce/0x2cf |
| [<ffffffff81027494>] sys_execve+0x43/0x5a |
| [<ffffffff8102918a>] stub_execve+0x6a/0xc0 |
| |
| -> #0 (&mm->mmap_sem){++++++}: |
| [<ffffffff81099aa4>] __lock_acquire+0xa11/0xd0f |
| [<ffffffff81099e7e>] lock_acquire+0xdc/0x102 |
| [<ffffffff81107251>] might_fault+0x89/0xac |
| [<ffffffff81139382>] fiemap_fill_next_extent+0x95/0xda |
| [<ffffffff811bcb43>] ext4_ext_fiemap_cb+0x138/0x157 |
| [<ffffffff811be069>] ext4_ext_walk_space+0x178/0x1f1 |
| [<ffffffff811be21e>] ext4_fiemap+0x13c/0x159 |
| [<ffffffff811390e6>] do_vfs_ioctl+0x348/0x4d6 |
| [<ffffffff811392ca>] sys_ioctl+0x56/0x79 |
| [<ffffffff81028cb2>] system_call_fastpath+0x16/0x1b |
| |
| other info that might help us debug this: |
| |
| 1 lock held by ureadahead/1855: |
| #0: (&ei->i_data_sem){++++..}, at: [<ffffffff811be1fd>] ext4_fiemap+0x11b/0x159 |
| |
| stack backtrace: |
| Pid: 1855, comm: ureadahead Not tainted 2.6.32-04115-gec044c5 #37 |
| Call Trace: |
| [<ffffffff81098c70>] print_circular_bug+0xa8/0xb7 |
| [<ffffffff81099aa4>] __lock_acquire+0xa11/0xd0f |
| [<ffffffff8102f229>] ? sched_clock+0x9/0xd |
| [<ffffffff81099e7e>] lock_acquire+0xdc/0x102 |
| [<ffffffff81107224>] ? might_fault+0x5c/0xac |
| [<ffffffff81107251>] might_fault+0x89/0xac |
| [<ffffffff81107224>] ? might_fault+0x5c/0xac |
| [<ffffffff81124b44>] ? __kmalloc+0x13b/0x18c |
| [<ffffffff81139382>] fiemap_fill_next_extent+0x95/0xda |
| [<ffffffff811bcb43>] ext4_ext_fiemap_cb+0x138/0x157 |
| [<ffffffff811bca0b>] ? ext4_ext_fiemap_cb+0x0/0x157 |
| [<ffffffff811be069>] ext4_ext_walk_space+0x178/0x1f1 |
| [<ffffffff811be21e>] ext4_fiemap+0x13c/0x159 |
| [<ffffffff81107224>] ? might_fault+0x5c/0xac |
| [<ffffffff811390e6>] do_vfs_ioctl+0x348/0x4d6 |
| [<ffffffff8129f6d0>] ? __up_read+0x8d/0x95 |
| [<ffffffff81517fb5>] ? retint_swapgs+0x13/0x1b |
| [<ffffffff811392ca>] sys_ioctl+0x56/0x79 |
| [<ffffffff81028cb2>] system_call_fastpath+0x16/0x1b |
| |
| Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| fs/ext4/extents.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/fs/ext4/extents.c |
| +++ b/fs/ext4/extents.c |
| @@ -1742,7 +1742,9 @@ int ext4_ext_walk_space(struct inode *in |
| while (block < last && block != EXT_MAX_BLOCK) { |
| num = last - block; |
| /* find extent for this block */ |
| + down_read(&EXT4_I(inode)->i_data_sem); |
| path = ext4_ext_find_extent(inode, block, path); |
| + up_read(&EXT4_I(inode)->i_data_sem); |
| if (IS_ERR(path)) { |
| err = PTR_ERR(path); |
| path = NULL; |
| @@ -3707,10 +3709,8 @@ int ext4_fiemap(struct inode *inode, str |
| * Walk the extent tree gathering extent information. |
| * ext4_ext_fiemap_cb will push extents back to user. |
| */ |
| - down_read(&EXT4_I(inode)->i_data_sem); |
| error = ext4_ext_walk_space(inode, start_blk, len_blks, |
| ext4_ext_fiemap_cb, fieinfo); |
| - up_read(&EXT4_I(inode)->i_data_sem); |
| } |
| |
| return error; |