| From: Lukas Czerner <lczerner@redhat.com> |
| Date: Sun, 13 May 2018 19:28:35 -0400 |
| Subject: ext4: update mtime in ext4_punch_hole even if no blocks are released |
| |
| commit eee597ac931305eff3d3fd1d61d6aae553bc0984 upstream. |
| |
| Currently in ext4_punch_hole we're going to skip the mtime update if |
| there are no actual blocks to release. However we've actually modified |
| the file by zeroing the partial block so the mtime should be updated. |
| |
| Moreover the sync and datasync handling is skipped as well, which is |
| also wrong. Fix it. |
| |
| Signed-off-by: Lukas Czerner <lczerner@redhat.com> |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Reported-by: Joe Habermann <joe.habermann@quantum.com> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/ext4/inode.c | 36 ++++++++++++++++++------------------ |
| 1 file changed, 18 insertions(+), 18 deletions(-) |
| |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -3749,28 +3749,28 @@ int ext4_punch_hole(struct inode *inode, |
| EXT4_BLOCK_SIZE_BITS(sb); |
| stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb); |
| |
| - /* If there are no blocks to remove, return now */ |
| - if (first_block >= stop_block) |
| - goto out_stop; |
| - |
| - down_write(&EXT4_I(inode)->i_data_sem); |
| - ext4_discard_preallocations(inode); |
| - |
| - ret = ext4_es_remove_extent(inode, first_block, |
| - stop_block - first_block); |
| - if (ret) { |
| - up_write(&EXT4_I(inode)->i_data_sem); |
| - goto out_stop; |
| - } |
| + /* If there are blocks to remove, do it */ |
| + if (stop_block > first_block) { |
| + |
| + down_write(&EXT4_I(inode)->i_data_sem); |
| + ext4_discard_preallocations(inode); |
| |
| - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
| - ret = ext4_ext_remove_space(inode, first_block, |
| - stop_block - 1); |
| - else |
| - ret = ext4_ind_remove_space(handle, inode, first_block, |
| - stop_block); |
| + ret = ext4_es_remove_extent(inode, first_block, |
| + stop_block - first_block); |
| + if (ret) { |
| + up_write(&EXT4_I(inode)->i_data_sem); |
| + goto out_stop; |
| + } |
| + |
| + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
| + ret = ext4_ext_remove_space(inode, first_block, |
| + stop_block - 1); |
| + else |
| + ret = ext4_ind_remove_space(handle, inode, first_block, |
| + stop_block); |
| |
| - up_write(&EXT4_I(inode)->i_data_sem); |
| + up_write(&EXT4_I(inode)->i_data_sem); |
| + } |
| if (IS_SYNC(inode)) |
| ext4_handle_sync(handle); |
| |