diff options
author | Theodore Ts'o <tytso@mit.edu> | 2018-12-25 00:56:33 -0500 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2019-04-04 16:14:06 +0100 |
commit | ee21615443472f57e622c8242648fad6e4b00ee4 (patch) | |
tree | b5b88f22d74e18d7e001c6169490389dd135f6a1 /fs | |
parent | 5b25a6d0d3d9830a7bd08236de0e7ee532e3b28c (diff) |
ext4: fix a potential fiemap/page fault deadlock w/ inline_data
commit 2b08b1f12cd664dc7d5c84ead9ff25ae97ad5491 upstream.
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>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'fs')
-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 d24247539ba0..c2bb71c98d43 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1846,12 +1846,12 @@ int ext4_inline_data_fiemap(struct inode *inode, physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; physical += offsetof(struct ext4_inode, i_block); - if (physical) - error = fiemap_fill_next_extent(fieinfo, start, physical, - inline_len, flags); brelse(iloc.bh); out: up_read(&EXT4_I(inode)->xattr_sem); + if (physical) + error = fiemap_fill_next_extent(fieinfo, start, physical, + inline_len, flags); return (error < 0 ? error : 0); } |