summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2018-12-25 00:56:33 -0500
committerTheodore Ts'o <tytso@mit.edu>2018-12-25 00:56:33 -0500
commit2b08b1f12cd664dc7d5c84ead9ff25ae97ad5491 (patch)
treeec4e19afec1556c8aeecef9a460a1208c1a71c83
parent812c0cab2c0dfad977605dbadf9148490ca5d93f (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.c6
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);
1897out: 1894out:
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