Rebase to 18f2c4fcebf2 and sync ext4 patches working directory
[ext4-patch-queue.git] / fix-potential-fiemap-page-fault-deadlock-with-inline_data
blobc646cd969ccd34fa6376c8c8339df0c4aa7ef78a
1 ext4: fix a potential fiemap/page fault deadlock w/ inline_data
3 The ext4_inline_data_fiemap() function calls fiemap_fill_next_extent()
4 while still holding the xattr semaphore.  This is not necessary and it
5 triggers a circular lockdep warning.  This is because
6 fiemap_fill_next_extent() could trigger a page fault when it writes
7 into page which triggers a page fault.  If that page is mmaped from
8 the inline file in question, this could very well result in a
9 deadlock.
11 This problem can be reproduced using generic/519 with a file system
12 configuration which has the inline_data feature enabled.
14 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
15 Cc: stable@kernel.org
16 ---
17  fs/ext4/inline.c | 6 +++---
18  1 file changed, 3 insertions(+), 3 deletions(-)
20 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
21 index 27373d88b5f0..56f6e1782d5f 100644
22 --- a/fs/ext4/inline.c
23 +++ b/fs/ext4/inline.c
24 @@ -1890,12 +1890,12 @@ int ext4_inline_data_fiemap(struct inode *inode,
25         physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data;
26         physical += offsetof(struct ext4_inode, i_block);
28 -       if (physical)
29 -               error = fiemap_fill_next_extent(fieinfo, start, physical,
30 -                                               inline_len, flags);
31         brelse(iloc.bh);
32  out:
33         up_read(&EXT4_I(inode)->xattr_sem);
34 +       if (physical)
35 +               error = fiemap_fill_next_extent(fieinfo, start, physical,
36 +                                               inline_len, flags);
37         return (error < 0 ? error : 0);
38  }