aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorEric Whitney <enwlinux@gmail.com>2014-11-23 00:59:39 -0500
committerTheodore Ts'o <tytso@mit.edu>2014-11-23 00:59:39 -0500
commit0756b908a364c217bc2d8063783992ffe338b143 (patch)
treed5c5effc3d6364c00ed9389c4299a4bf1890a834 /fs/ext4
parent345ee947482f1c787b31014008586b8f512af1bd (diff)
ext4: fix end of region partial cluster handling
ext4_ext_remove_space() can incorrectly free a partial_cluster if EAGAIN is encountered while truncating or punching. Extent removal should be retried in this case. It also fails to free a partial cluster when the punched region begins at the start of a file on that unaligned cluster and where the entire file has not been punched. Remove the requirement that all blocks in the file must have been freed in order to free the partial cluster. Signed-off-by: Eric Whitney <enwlinux@gmail.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/extents.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 841adf05e287..9eae2f4916ce 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3009,16 +3009,18 @@ again:
3009 trace_ext4_ext_remove_space_done(inode, start, end, depth, 3009 trace_ext4_ext_remove_space_done(inode, start, end, depth,
3010 partial_cluster, path->p_hdr->eh_entries); 3010 partial_cluster, path->p_hdr->eh_entries);
3011 3011
3012 /* If we still have something in the partial cluster and we have removed 3012 /*
3013 * If we still have something in the partial cluster and we have removed
3013 * even the first extent, then we should free the blocks in the partial 3014 * even the first extent, then we should free the blocks in the partial
3014 * cluster as well. */ 3015 * cluster as well. (This code will only run when there are no leaves
3015 if (partial_cluster > 0 && path->p_hdr->eh_entries == 0) { 3016 * to the immediate left of the truncated/punched region.)
3016 int flags = get_default_free_blocks_flags(inode); 3017 */
3017 3018 if (partial_cluster > 0 && err == 0) {
3019 /* don't zero partial_cluster since it's not used afterwards */
3018 ext4_free_blocks(handle, inode, NULL, 3020 ext4_free_blocks(handle, inode, NULL,
3019 EXT4_C2B(sbi, partial_cluster), 3021 EXT4_C2B(sbi, partial_cluster),
3020 sbi->s_cluster_ratio, flags); 3022 sbi->s_cluster_ratio,
3021 partial_cluster = 0; 3023 get_default_free_blocks_flags(inode));
3022 } 3024 }
3023 3025
3024 /* TODO: flexible tree reduction should be here */ 3026 /* TODO: flexible tree reduction should be here */