diff options
author | Theodore Ts'o <tytso@mit.edu> | 2018-12-25 00:56:33 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2018-12-25 00:56:33 -0500 |
commit | 2b08b1f12cd664dc7d5c84ead9ff25ae97ad5491 (patch) | |
tree | ec4e19afec1556c8aeecef9a460a1208c1a71c83 | |
parent | 812c0cab2c0dfad977605dbadf9148490ca5d93f (diff) |
ext4: fix a potential fiemap/page fault deadlock w/ inline_data
The ext4_inline_data_fiemap() function calls fiemap_fill_next_extent()
while still holding the xattr semaphore. This is not necessary and it
triggers a circular lockdep warning. This is because
fiemap_fill_next_extent() could trigger a page fault when it writes
into page which triggers a page fault. If that page is mmaped from
the inline file in question, this could very well result in a
deadlock.
This problem can be reproduced using generic/519 with a file system
configuration which has the inline_data feature enabled.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
-rw-r--r-- | fs/ext4/inline.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 27373d88b5f0..56f6e1782d5f 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -1890,12 +1890,12 @@ int ext4_inline_data_fiemap(struct inode *inode, | |||
1890 | physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; | 1890 | physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; |
1891 | physical += offsetof(struct ext4_inode, i_block); | 1891 | physical += offsetof(struct ext4_inode, i_block); |
1892 | 1892 | ||
1893 | if (physical) | ||
1894 | error = fiemap_fill_next_extent(fieinfo, start, physical, | ||
1895 | inline_len, flags); | ||
1896 | brelse(iloc.bh); | 1893 | brelse(iloc.bh); |
1897 | out: | 1894 | out: |
1898 | up_read(&EXT4_I(inode)->xattr_sem); | 1895 | up_read(&EXT4_I(inode)->xattr_sem); |
1896 | if (physical) | ||
1897 | error = fiemap_fill_next_extent(fieinfo, start, physical, | ||
1898 | inline_len, flags); | ||
1899 | return (error < 0 ? error : 0); | 1899 | return (error < 0 ? error : 0); |
1900 | } | 1900 | } |
1901 | 1901 | ||