aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2013-07-01 08:12:39 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-07-01 08:12:39 -0400
commite1be3a928ee0b0b2a893695e6dd5c5dbe293af16 (patch)
treea03fcedb0198f00c02ace3814a3fe27772cf2dcf /fs
parent42c832debbbf819f6c4ad8601baa559c44105ba4 (diff)
ext4: only zero partial blocks in ext4_zero_partial_blocks()
Currently if we pass range into ext4_zero_partial_blocks() which covers entire block we would attempt to zero it even though we should only zero unaligned part of the block. Fix this by checking whether the range covers the whole block skip zeroing if so. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/inode.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 09942341dfae..502a9e1f5aa3 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3424,33 +3424,36 @@ int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
3424{ 3424{
3425 struct super_block *sb = inode->i_sb; 3425 struct super_block *sb = inode->i_sb;
3426 struct address_space *mapping = inode->i_mapping; 3426 struct address_space *mapping = inode->i_mapping;
3427 unsigned partial = lstart & (sb->s_blocksize - 1); 3427 unsigned partial_start, partial_end;
3428 ext4_fsblk_t start, end; 3428 ext4_fsblk_t start, end;
3429 loff_t byte_end = (lstart + length - 1); 3429 loff_t byte_end = (lstart + length - 1);
3430 int err = 0; 3430 int err = 0;
3431 3431
3432 partial_start = lstart & (sb->s_blocksize - 1);
3433 partial_end = byte_end & (sb->s_blocksize - 1);
3434
3432 start = lstart >> sb->s_blocksize_bits; 3435 start = lstart >> sb->s_blocksize_bits;
3433 end = byte_end >> sb->s_blocksize_bits; 3436 end = byte_end >> sb->s_blocksize_bits;
3434 3437
3435 /* Handle partial zero within the single block */ 3438 /* Handle partial zero within the single block */
3436 if (start == end) { 3439 if (start == end &&
3440 (partial_start || (partial_end != sb->s_blocksize - 1))) {
3437 err = ext4_block_zero_page_range(handle, mapping, 3441 err = ext4_block_zero_page_range(handle, mapping,
3438 lstart, length); 3442 lstart, length);
3439 return err; 3443 return err;
3440 } 3444 }
3441 /* Handle partial zero out on the start of the range */ 3445 /* Handle partial zero out on the start of the range */
3442 if (partial) { 3446 if (partial_start) {
3443 err = ext4_block_zero_page_range(handle, mapping, 3447 err = ext4_block_zero_page_range(handle, mapping,
3444 lstart, sb->s_blocksize); 3448 lstart, sb->s_blocksize);
3445 if (err) 3449 if (err)
3446 return err; 3450 return err;
3447 } 3451 }
3448 /* Handle partial zero out on the end of the range */ 3452 /* Handle partial zero out on the end of the range */
3449 partial = byte_end & (sb->s_blocksize - 1); 3453 if (partial_end != sb->s_blocksize - 1)
3450 if (partial != sb->s_blocksize - 1)
3451 err = ext4_block_zero_page_range(handle, mapping, 3454 err = ext4_block_zero_page_range(handle, mapping,
3452 byte_end - partial, 3455 byte_end - partial_end,
3453 partial + 1); 3456 partial_end + 1);
3454 return err; 3457 return err;
3455} 3458}
3456 3459