diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2014-12-02 16:11:20 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-12-02 16:11:20 -0500 |
commit | d952d69e268f833c85c0bafee9f67f9dba85044b (patch) | |
tree | 8292c9e39fa90e279a9e1698f894d400579b6c5b /fs/ext4/inline.c | |
parent | 5cc28a9eaab21ce7ded7845b32e2eafc4bbeb175 (diff) |
ext4: ext4_inline_data_fiemap should respect callers argument
Currently ext4_inline_data_fiemap ignores requested arguments (start
and len) which may lead endless loop if start != 0. Also fix incorrect
extent length determination.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inline.c')
-rw-r--r-- | fs/ext4/inline.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index efdcede40c22..b32d77bfb3a1 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -1808,11 +1808,12 @@ int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) | |||
1808 | 1808 | ||
1809 | int ext4_inline_data_fiemap(struct inode *inode, | 1809 | int ext4_inline_data_fiemap(struct inode *inode, |
1810 | struct fiemap_extent_info *fieinfo, | 1810 | struct fiemap_extent_info *fieinfo, |
1811 | int *has_inline) | 1811 | int *has_inline, __u64 start, __u64 len) |
1812 | { | 1812 | { |
1813 | __u64 physical = 0; | 1813 | __u64 physical = 0; |
1814 | __u64 length; | 1814 | __u64 inline_len; |
1815 | __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_LAST; | 1815 | __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | |
1816 | FIEMAP_EXTENT_LAST; | ||
1816 | int error = 0; | 1817 | int error = 0; |
1817 | struct ext4_iloc iloc; | 1818 | struct ext4_iloc iloc; |
1818 | 1819 | ||
@@ -1821,6 +1822,13 @@ int ext4_inline_data_fiemap(struct inode *inode, | |||
1821 | *has_inline = 0; | 1822 | *has_inline = 0; |
1822 | goto out; | 1823 | goto out; |
1823 | } | 1824 | } |
1825 | inline_len = min_t(size_t, ext4_get_inline_size(inode), | ||
1826 | i_size_read(inode)); | ||
1827 | if (start >= inline_len) | ||
1828 | goto out; | ||
1829 | if (start + len < inline_len) | ||
1830 | inline_len = start + len; | ||
1831 | inline_len -= start; | ||
1824 | 1832 | ||
1825 | error = ext4_get_inode_loc(inode, &iloc); | 1833 | error = ext4_get_inode_loc(inode, &iloc); |
1826 | if (error) | 1834 | if (error) |
@@ -1829,11 +1837,10 @@ int ext4_inline_data_fiemap(struct inode *inode, | |||
1829 | physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; | 1837 | physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; |
1830 | physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; | 1838 | physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; |
1831 | physical += offsetof(struct ext4_inode, i_block); | 1839 | physical += offsetof(struct ext4_inode, i_block); |
1832 | length = i_size_read(inode); | ||
1833 | 1840 | ||
1834 | if (physical) | 1841 | if (physical) |
1835 | error = fiemap_fill_next_extent(fieinfo, 0, physical, | 1842 | error = fiemap_fill_next_extent(fieinfo, start, physical, |
1836 | length, flags); | 1843 | inline_len, flags); |
1837 | brelse(iloc.bh); | 1844 | brelse(iloc.bh); |
1838 | out: | 1845 | out: |
1839 | up_read(&EXT4_I(inode)->xattr_sem); | 1846 | up_read(&EXT4_I(inode)->xattr_sem); |