diff options
Diffstat (limited to 'fs/ext4/extents.c')
| -rw-r--r-- | fs/ext4/extents.c | 31 | 
1 files changed, 31 insertions, 0 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ce394706c61a..844773d3b64b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4862,6 +4862,28 @@ static const struct iomap_ops ext4_iomap_xattr_ops = {  	.iomap_begin		= ext4_iomap_xattr_begin,  }; +static int ext4_fiemap_check_ranges(struct inode *inode, u64 start, u64 *len) +{ +	u64 maxbytes; + +	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) +		maxbytes = inode->i_sb->s_maxbytes; +	else +		maxbytes = EXT4_SB(inode->i_sb)->s_bitmap_maxbytes; + +	if (*len == 0) +		return -EINVAL; +	if (start > maxbytes) +		return -EFBIG; + +	/* +	 * Shrink request scope to what the fs can actually handle. +	 */ +	if (*len > maxbytes || (maxbytes - *len) < start) +		*len = maxbytes - start; +	return 0; +} +  static int _ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  			__u64 start, __u64 len, bool from_es_cache)  { @@ -4882,6 +4904,15 @@ static int _ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  	if (fiemap_check_flags(fieinfo, ext4_fiemap_flags))  		return -EBADR; +	/* +	 * For bitmap files the maximum size limit could be smaller than +	 * s_maxbytes, so check len here manually instead of just relying on the +	 * generic check. +	 */ +	error = ext4_fiemap_check_ranges(inode, start, &len); +	if (error) +		return error; +  	if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {  		fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR;  		error = iomap_fiemap(inode, fieinfo, start, len,  | 
