diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 8fd6c567964aa5990f0df8f8872920c2e2882206..91ae46098ea4a54727f5d5d114b2f2b3c878307f 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3023,6 +3023,14 @@ static int ext4_convert_unwritten_extents_dio(handle_t *handle, return err; } +static void unmap_underlying_metadata_blocks(struct block_device *bdev, + sector_t block, int count) +{ + int i; + for (i = 0; i < count; i++) + unmap_underlying_metadata(bdev, block + i); +} + static int ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, ext4_lblk_t iblock, unsigned int max_blocks, @@ -3098,6 +3106,18 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, } else allocated = ret; set_buffer_new(bh_result); + /* + * if we allocated more blocks than requested + * we need to make sure we unmap the extra block + * allocated. The actual needed block will get + * unmapped later when we find the buffer_head marked + * new. + */ + if (allocated > max_blocks) { + unmap_underlying_metadata_blocks(inode->i_sb->s_bdev, + newblock + max_blocks, + allocated - max_blocks); + } map_out: set_buffer_mapped(bh_result); out1: